Add a kubectl create secret tls command

pull/6/head
Prashanth Balasubramanian 2016-04-24 12:46:58 -07:00
parent cb9a85166c
commit daa8e29c5b
15 changed files with 835 additions and 7 deletions

View File

@ -26,6 +26,7 @@ docs/man/man1/kubectl-create-configmap.1
docs/man/man1/kubectl-create-namespace.1
docs/man/man1/kubectl-create-secret-docker-registry.1
docs/man/man1/kubectl-create-secret-generic.1
docs/man/man1/kubectl-create-secret-tls.1
docs/man/man1/kubectl-create-secret.1
docs/man/man1/kubectl-create-serviceaccount.1
docs/man/man1/kubectl-create.1
@ -82,6 +83,7 @@ docs/user-guide/kubectl/kubectl_create_namespace.md
docs/user-guide/kubectl/kubectl_create_secret.md
docs/user-guide/kubectl/kubectl_create_secret_docker-registry.md
docs/user-guide/kubectl/kubectl_create_secret_generic.md
docs/user-guide/kubectl/kubectl_create_secret_tls.md
docs/user-guide/kubectl/kubectl_create_serviceaccount.md
docs/user-guide/kubectl/kubectl_delete.md
docs/user-guide/kubectl/kubectl_describe.md

View File

@ -763,6 +763,69 @@ _kubectl_create_secret_docker-registry()
noun_aliases=()
}
_kubectl_create_secret_tls()
{
last_command="kubectl_create_secret_tls"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--cert=")
flags+=("--dry-run")
flags+=("--generator=")
flags+=("--key=")
flags+=("--no-headers")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags_with_completion+=("--schema-cache-dir")
flags_completion+=("_filedir")
flags+=("--show-all")
flags+=("-a")
flags+=("--show-labels")
flags+=("--sort-by=")
flags+=("--template=")
flags_with_completion+=("--template")
flags_completion+=("_filedir")
flags+=("--validate")
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--as=")
flags+=("--certificate-authority=")
flags+=("--client-certificate=")
flags+=("--client-key=")
flags+=("--cluster=")
flags+=("--context=")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
flags+=("--log-backtrace-at=")
flags+=("--log-dir=")
flags+=("--log-flush-frequency=")
flags+=("--logtostderr")
flags+=("--match-server-version")
flags+=("--namespace=")
flags_with_completion+=("--namespace")
flags_completion+=("__kubectl_get_namespaces")
flags+=("--password=")
flags+=("--server=")
two_word_flags+=("-s")
flags+=("--stderrthreshold=")
flags+=("--token=")
flags+=("--user=")
flags+=("--username=")
flags+=("--v=")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
noun_aliases=()
}
_kubectl_create_secret_generic()
{
last_command="kubectl_create_secret_generic"
@ -832,6 +895,7 @@ _kubectl_create_secret()
last_command="kubectl_create_secret"
commands=()
commands+=("docker-registry")
commands+=("tls")
commands+=("generic")
flags=()

View File

@ -208,7 +208,7 @@ by creating a dockercfg secret and attaching it to your service account.
.nf
# If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
$ kubectl create secret docker\-registry my\-secret \-\-docker\-server=DOCKER\_REGISTRY\_SERVER \-\-docker\-username=DOCKER\_USER \-\-docker\-password=DOCKER\_PASSWORD \-\-docker\-email=DOCKER\_EMAIL
kubectl create secret docker\-registry my\-secret \-\-docker\-server=DOCKER\_REGISTRY\_SERVER \-\-docker\-username=DOCKER\_USER \-\-docker\-password=DOCKER\_PASSWORD \-\-docker\-email=DOCKER\_EMAIL
.fi
.RE

View File

@ -0,0 +1,200 @@
.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015" ""
.SH NAME
.PP
kubectl create secret tls \- Create a TLS secret.
.SH SYNOPSIS
.PP
\fBkubectl create secret tls\fP [OPTIONS]
.SH DESCRIPTION
.PP
Create a TLS secret from the given public/private key pair.
.PP
The public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.
.SH OPTIONS
.PP
\fB\-\-cert\fP=""
Path to PEM encoded public key certificate.
.PP
\fB\-\-dry\-run\fP=false
If true, only print the object that would be sent, without sending it.
.PP
\fB\-\-generator\fP="secret\-for\-tls/v1"
The name of the API generator to use.
.PP
\fB\-\-key\fP=""
Path to private key associated with given certificate.
.PP
\fB\-\-no\-headers\fP=false
When using the default output, don't print headers.
.PP
\fB\-o\fP, \fB\-\-output\fP=""
Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
\[la]http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md\[ra]].
.PP
\fB\-\-output\-version\fP=""
Output the formatted object with the given group version (for ex: 'extensions/v1beta1').
.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
.PP
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
.PP
\fB\-a\fP, \fB\-\-show\-all\fP=false
When printing, show all resources (default hide terminated pods.)
.PP
\fB\-\-show\-labels\fP=false
When printing, show all labels as the last column (default hide labels column)
.PP
\fB\-\-sort\-by\fP=""
If non\-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
.PP
\fB\-\-template\fP=""
Template string or path to template file to use when \-o=go\-template, \-o=go\-template\-file. The template format is golang templates [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]].
.PP
\fB\-\-validate\fP=true
If true, use a schema to validate the input before sending it
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
\fB\-\-alsologtostderr\fP=false
log to standard error as well as files
.PP
\fB\-\-api\-version\fP=""
DEPRECATED: The API version to use when talking to the server
.PP
\fB\-\-as\fP=""
Username to impersonate for the operation.
.PP
\fB\-\-certificate\-authority\fP=""
Path to a cert. file for the certificate authority.
.PP
\fB\-\-client\-certificate\fP=""
Path to a client certificate file for TLS.
.PP
\fB\-\-client\-key\fP=""
Path to a client key file for TLS.
.PP
\fB\-\-cluster\fP=""
The name of the kubeconfig cluster to use
.PP
\fB\-\-context\fP=""
The name of the kubeconfig context to use
.PP
\fB\-\-insecure\-skip\-tls\-verify\fP=false
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
.PP
\fB\-\-kubeconfig\fP=""
Path to the kubeconfig file to use for CLI requests.
.PP
\fB\-\-log\-backtrace\-at\fP=:0
when logging hits line file:N, emit a stack trace
.PP
\fB\-\-log\-dir\fP=""
If non\-empty, write log files in this directory
.PP
\fB\-\-log\-flush\-frequency\fP=5s
Maximum number of seconds between log flushes
.PP
\fB\-\-logtostderr\fP=true
log to standard error instead of files
.PP
\fB\-\-match\-server\-version\fP=false
Require server version to match client version
.PP
\fB\-\-namespace\fP=""
If present, the namespace scope for this CLI request.
.PP
\fB\-\-password\fP=""
Password for basic authentication to the API server.
.PP
\fB\-s\fP, \fB\-\-server\fP=""
The address and port of the Kubernetes API server
.PP
\fB\-\-stderrthreshold\fP=2
logs at or above this threshold go to stderr
.PP
\fB\-\-token\fP=""
Bearer token for authentication to the API server.
.PP
\fB\-\-user\fP=""
The name of the kubeconfig user to use
.PP
\fB\-\-username\fP=""
Username for basic authentication to the API server.
.PP
\fB\-\-v\fP=0
log level for V logs
.PP
\fB\-\-vmodule\fP=
comma\-separated list of pattern=N settings for file\-filtered logging
.SH EXAMPLE
.PP
.RS
.nf
# Create a new TLS secret named tls\-secret with the given key pair:
kubectl create secret tls tls\-secret \-\-cert=path/to/tls.cert \-\-key=path/to/tls.key
.fi
.RE
.SH SEE ALSO
.PP
\fBkubectl\-create\-secret(1)\fP,
.SH HISTORY
.PP
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!

View File

@ -116,7 +116,7 @@ Create a secret using specified subcommand.
.SH SEE ALSO
.PP
\fBkubectl\-create(1)\fP, \fBkubectl\-create\-secret\-docker\-registry(1)\fP, \fBkubectl\-create\-secret\-generic(1)\fP,
\fBkubectl\-create(1)\fP, \fBkubectl\-create\-secret\-docker\-registry(1)\fP, \fBkubectl\-create\-secret\-tls(1)\fP, \fBkubectl\-create\-secret\-generic(1)\fP,
.SH HISTORY

View File

@ -78,8 +78,9 @@ kubectl create secret
* [kubectl create](kubectl_create.md) - Create a resource by filename or stdin
* [kubectl create secret docker-registry](kubectl_create_secret_docker-registry.md) - Create a secret for use with a Docker registry.
* [kubectl create secret generic](kubectl_create_secret_generic.md) - Create a secret from a local file, directory or literal value.
* [kubectl create secret tls](kubectl_create_secret_tls.md) - Create a TLS secret.
###### Auto generated by spf13/cobra on 5-Apr-2016
###### Auto generated by spf13/cobra on 25-Apr-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_secret.md?pixel)]()

View File

@ -61,7 +61,7 @@ kubectl create secret docker-registry NAME --docker-username=user --docker-passw
```
# If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
$ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
```
### Options
@ -118,7 +118,7 @@ kubectl create secret docker-registry NAME --docker-username=user --docker-passw
* [kubectl create secret](kubectl_create_secret.md) - Create a secret using specified subcommand.
###### Auto generated by spf13/cobra on 5-Apr-2016
###### Auto generated by spf13/cobra on 16-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_secret_docker-registry.md?pixel)]()

View File

@ -0,0 +1,108 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## kubectl create secret tls
Create a TLS secret.
### Synopsis
Create a TLS secret from the given public/private key pair.
The public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.
```
kubectl create secret tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]
```
### Examples
```
# Create a new TLS secret named tls-secret with the given key pair:
kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key
```
### Options
```
--cert="": Path to PEM encoded public key certificate.
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
--generator="secret-for-tls/v1": The name of the API generator to use.
--key="": Path to private key associated with given certificate.
--no-headers[=false]: When using the default output, don't print headers.
-o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].
--output-version="": Output the formatted object with the given group version (for ex: 'extensions/v1beta1').
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
--show-labels[=false]: When printing, show all labels as the last column (default hide labels column)
--sort-by="": If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
--template="": Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate[=true]: If true, use a schema to validate the input before sending it
```
### Options inherited from parent commands
```
--alsologtostderr[=false]: log to standard error as well as files
--as="": Username to impersonate for the operation.
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client certificate file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify[=false]: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log-backtrace-at=:0: when logging hits line file:N, emit a stack trace
--log-dir="": If non-empty, write log files in this directory
--log-flush-frequency=5s: Maximum number of seconds between log flushes
--logtostderr[=true]: log to standard error instead of files
--match-server-version[=false]: Require server version to match client version
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kubectl create secret](kubectl_create_secret.md) - Create a secret using specified subcommand.
###### Auto generated by spf13/cobra on 16-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_secret_tls.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -1155,6 +1155,16 @@ __EOF__
# Clean-up
kubectl delete secret test-secret --namespace=test-secrets
### Create a tls secret
# Pre-condition: no SECRET exists
kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
# Command
kubectl create secret tls test-secret --namespace=test-secrets --key=hack/testdata/tls.key --cert=hack/testdata/tls.crt
kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/tls'
# Clean-up
kubectl delete secret test-secret --namespace=test-secrets
### Create a secret using output flags
# Pre-condition: no secret exists
kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
@ -2009,7 +2019,7 @@ __EOF__
object="all -l'app=cassandra'"
request="{{range.items}}{{range .metadata.labels}}{{.}}:{{end}}{{end}}"
# all 4 cassandra's might not be in the request immediately...
# all 4 cassandra's might not be in the request immediately...
kube::test::get_object_assert "$object" "$request" 'cassandra:cassandra:cassandra:cassandra:' || \
kube::test::get_object_assert "$object" "$request" 'cassandra:cassandra:cassandra:' || \
kube::test::get_object_assert "$object" "$request" 'cassandra:cassandra:'

19
hack/testdata/tls.crt vendored Normal file
View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDKzCCAhOgAwIBAgIJAP6zX1i14mEuMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
BAMMC2V4YW1wbGUuY29tMRQwEgYDVQQKDAtleGFtcGxlLmNvbTAeFw0xNjA1MTUw
MDQ0NThaFw0xNzA1MTUwMDQ0NThaMCwxFDASBgNVBAMMC2V4YW1wbGUuY29tMRQw
EgYDVQQKDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAL/rrmHnmFYPhXaSJD4H8b0018HDr14GJsSEj29aQ9TKffoY7avcc+1ETrfA
F8WlXjzqez0OhmecBgQloaNU0IKpLm1DIwFanzjejrooGsSAGm510KGKC/K6XfcW
EPUiYWc35XLRqM4n7X9lqLbzMFdZvEJYRurPuzx7ZSw+UF3QJqPiBx3fbIPYHCIe
rMHyh1OhZFRPuX6lLxGoDUGu5C+2MQityhZWUTXvRlh7v4Cmb3oD5a+1VGSjM/Kf
EcXxK4SLDiECHSVdHpvjNnPi1lVXx6/Yel9+95X/rwaILJ4UNuCWp3ixn8iBr+vC
7ttVj8HMUCkfC7aGaZVcudpre5UCAwEAAaNQME4wHQYDVR0OBBYEFMqQZOeB0B/V
pPgBNs23SW2aRZsZMB8GA1UdIwQYMBaAFMqQZOeB0B/VpPgBNs23SW2aRZsZMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEtLa1+ovgKHHr3YKUyrbWi2
SbNmrMrQIdomdNnhQn/3tYl2RG/twUIpi2LaxLC8+n+hhVO9Gy1hy18xQ9bXDKtC
I30dml8qmNqqCpCxTz6jSh7kxiBF8+7lj6B3zoN4JLVDdmp+8iQwecd+rgB5jW8O
c333juUWA/c9QC9VO6yeDZs4EBkD2/a1GRtMkU2nkk7jk4QhMcjSxFKH+7ROC6yN
/+80NcHdDitVt0VRqogWusZDCMeZFwGVrfPVT8iYfP8lP7p6HBkYzvVP6SaMn76P
/tGxy/BYC4mGosiyhdfLBQS/Q1bkvNhu2O6Y9hqWE6tLNy+YIC3A0ON5/xN36dY=
-----END CERTIFICATE-----

28
hack/testdata/tls.key vendored Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC/665h55hWD4V2
kiQ+B/G9NNfBw69eBibEhI9vWkPUyn36GO2r3HPtRE63wBfFpV486ns9DoZnnAYE
JaGjVNCCqS5tQyMBWp843o66KBrEgBpuddChigvyul33FhD1ImFnN+Vy0ajOJ+1/
Zai28zBXWbxCWEbqz7s8e2UsPlBd0Caj4gcd32yD2BwiHqzB8odToWRUT7l+pS8R
qA1BruQvtjEIrcoWVlE170ZYe7+Apm96A+WvtVRkozPynxHF8SuEiw4hAh0lXR6b
4zZz4tZVV8ev2HpffveV/68GiCyeFDbglqd4sZ/Iga/rwu7bVY/BzFApHwu2hmmV
XLnaa3uVAgMBAAECggEAG+kvnCdtPR7Wvw6z3J2VJ3oW4qQNzfPBEZVhssUC1mB4
f7W+Yt8VsOzdMdXq3yCUmvFS6OdC3rCPI21Bm5pLFKV8DgHUhm7idwfO4/3PHsKu
lV/m7odAA5Xc8oEwCCZu2e8EHHWnQgwGex+SsMCfSCTRvyhNb/qz9TDQ3uVVFL9e
9a4OKqZl/GlRspJSuXhy+RSVulw9NjeX1VRjIbhqpdXAmQNXgShA+gZSQh8T/tgv
XQYsMtg+FUDvcunJQf4OW5BY7IenYBV/GvsnJU8L7oD0wjNSAwe/iLKqV/NpYhre
QR4DsGnmoRYlUlHdHFTTJpReDjWm+vH3T756yDdFAQKBgQD2/sP5dM/aEW7Z1TgS
TG4ts1t8Rhe9escHxKZQR81dfOxBeCJMBDm6ySfR8rvyUM4VsogxBL/RhRQXsjJM
7wN08MhdiXG0J5yy/oNo8W6euD8m8Mk1UmqcZjSgV4vA7zQkvkr6DRJdybKsT9mE
jouEwev8sceS6iBpPw/+Ws8z1QKBgQDG6uYHMfMcS844xKQQWhargdN2XBzeG6TV
YXfNFstNpD84d9zIbpG/AKJF8fKrseUhXkJhkDjFGJTriD3QQsntOFaDOrHMnveV
zGzvC4OTFUUFHe0SVJ0HuLf8YCHoZ+DXEeCKCN6zBXnUue+bt3NvLOf2yN5o9kYx
SIa8O1vIwQKBgEdONXWG65qg/ceVbqKZvhUjen3eHmxtTZhIhVsX34nlzq73567a
aXArMnvB/9Bs05IgAIFmRZpPOQW+RBdByVWxTabzTwgbh3mFUJqzWKQpvNGZIf1q
1axhNUA1BfulEwCojyyxKWQ6HoLwanOCU3T4JxDEokEfpku8EPn1bWwhAoGAAN8A
eOGYHfSbB5ac3VF3rfKYmXkXy0U1uJV/r888vq9Mc5PazKnnS33WOBYyKNxTk4zV
H5ZBGWPdKxbipmnUdox7nIGCS9IaZXaKt5VGUzuRnM8fvafPNDxz2dAV9e2Wh3qV
kCUvzHrmqK7TxMvN3pvEvEju6GjDr+2QYXylD0ECgYAGK5r+y+EhtKkYFLeYReUt
znvSsWq+JCQH/cmtZLaVOldCaMRL625hSl3XPPcMIHE14xi3d4njoXWzvzPcg8L6
vNXk3GiNldACS+vwk4CwEqe5YlZRm5doD07wIdsg2zRlnKsnXNM152OwgmcchDul
rLTt0TTazzwBCgCD0Jkoqg==
-----END PRIVATE KEY-----

View File

@ -37,6 +37,7 @@ func NewCmdCreateSecret(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
},
}
cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, cmdOut))
cmd.AddCommand(NewCmdCreateSecretTLS(f, cmdOut))
cmd.AddCommand(NewCmdCreateSecretGeneric(f, cmdOut))
return cmd
@ -130,7 +131,7 @@ nodes to pull images on your behalf, they have to have the credentials. You can
by creating a dockercfg secret and attaching it to your service account.`
secretForDockerRegistryExample = ` # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
$ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`
kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`
)
// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries
@ -192,3 +193,65 @@ func CreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
}
const (
secretForTLSLong = `
Create a TLS secret from the given public/private key pair.
The public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.`
secretForTLSExample = ` # Create a new TLS secret named tls-secret with the given key pair:
kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`
)
// NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries
func NewCmdCreateSecretTLS(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]",
Short: "Create a TLS secret.",
Long: secretForTLSLong,
Example: secretForTLSExample,
Run: func(cmd *cobra.Command, args []string) {
err := CreateSecretTLS(f, cmdOut, cmd, args)
cmdutil.CheckErr(err)
},
}
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForTLSV1GeneratorName)
cmd.Flags().String("cert", "", "Path to PEM encoded public key certificate.")
cmd.Flags().String("key", "", "Path to private key associated with given certificate.")
return cmd
}
// CreateSecretTLS is the implementation of the create secret tls command
func CreateSecretTLS(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args)
if err != nil {
return err
}
requiredFlags := []string{"cert", "key"}
for _, requiredFlag := range requiredFlags {
if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 {
return cmdutil.UsageError(cmd, "flag %s is required", requiredFlag)
}
}
var generator kubectl.StructuredGenerator
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
case cmdutil.SecretForTLSV1GeneratorName:
generator = &kubectl.SecretForTLSGeneratorV1{
Name: name,
Key: cmdutil.GetFlagString(cmd, "key"),
Cert: cmdutil.GetFlagString(cmd, "cert"),
}
default:
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName))
}
return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
Name: name,
StructuredGenerator: generator,
DryRun: cmdutil.GetFlagBool(cmd, "dry-run"),
OutputFormat: cmdutil.GetFlagString(cmd, "output"),
})
}

View File

@ -157,6 +157,7 @@ const (
NamespaceV1GeneratorName = "namespace/v1"
SecretV1GeneratorName = "secret/v1"
SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1"
SecretForTLSV1GeneratorName = "secret-for-tls/v1"
ConfigMapV1GeneratorName = "configmap/v1"
)
@ -186,6 +187,10 @@ func DefaultGenerators(cmdName string) map[string]kubectl.Generator {
generators["secret-for-docker-registry"] = map[string]kubectl.Generator{
SecretForDockerRegistryV1GeneratorName: kubectl.SecretForDockerRegistryGeneratorV1{},
}
generators["secret-for-tls"] = map[string]kubectl.Generator{
SecretForTLSV1GeneratorName: kubectl.SecretForTLSGeneratorV1{},
}
return generators[cmdName]
}

View File

@ -0,0 +1,124 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"crypto/tls"
"fmt"
"io/ioutil"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/runtime"
)
// SecretForTLSGeneratorV1 supports stable generation of a TLS secret.
type SecretForTLSGeneratorV1 struct {
// Name is the name of this TLS secret.
Name string
// Key is the path to the user's private key.
Key string
// Cert is the path to the user's public key certificate.
Cert string
}
// Ensure it supports the generator pattern that uses parameter injection
var _ Generator = &SecretForTLSGeneratorV1{}
// Ensure it supports the generator pattern that uses parameters specified during construction
var _ StructuredGenerator = &SecretForTLSGeneratorV1{}
// Generate returns a secret using the specified parameters
func (s SecretForTLSGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
err := ValidateParams(s.ParamNames(), genericParams)
if err != nil {
return nil, err
}
params := map[string]string{}
for key, value := range genericParams {
strVal, isString := value.(string)
if !isString {
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
}
params[key] = strVal
}
delegate := &SecretForTLSGeneratorV1{
Name: params["name"],
Key: params["key"],
Cert: params["cert"],
}
return delegate.StructuredGenerate()
}
// StructuredGenerate outputs a secret object using the configured fields
func (s SecretForTLSGeneratorV1) StructuredGenerate() (runtime.Object, error) {
if err := s.validate(); err != nil {
return nil, err
}
tlsCrt, err := readFile(s.Cert)
if err != nil {
return nil, err
}
tlsKey, err := readFile(s.Key)
if err != nil {
return nil, err
}
secret := &api.Secret{}
secret.Name = s.Name
secret.Type = api.SecretTypeTLS
secret.Data = map[string][]byte{}
secret.Data[api.TLSCertKey] = []byte(tlsCrt)
secret.Data[api.TLSPrivateKeyKey] = []byte(tlsKey)
return secret, nil
}
// readFile just reads a file into a byte array.
func readFile(file string) ([]byte, error) {
b, err := ioutil.ReadFile(file)
if err != nil {
return []byte{}, fmt.Errorf("Cannot read file %v, %v", file, err)
}
return b, nil
}
// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern
func (s SecretForTLSGeneratorV1) ParamNames() []GeneratorParam {
return []GeneratorParam{
{"name", true},
{"key", true},
{"cert", true},
}
}
// validate validates required fields are set to support structured generation
func (s SecretForTLSGeneratorV1) validate() error {
// TODO: This is not strictly necessary. We can generate a self signed cert
// if no key/cert is given. The only requiredment is that we either get both
// or none. See test/e2e/ingress_utils for self signed cert generation.
if len(s.Key) == 0 {
return fmt.Errorf("key must be specified.")
}
if len(s.Cert) == 0 {
return fmt.Errorf("certificate must be specified.")
}
if _, err := tls.LoadX509KeyPair(s.Cert, s.Key); err != nil {
return fmt.Errorf("failed to load key pair %v", err)
}
// TODO: Add more validation.
// 1. If the certificate contains intermediates, it is a valid chain.
// 2. Format etc.
return nil
}

View File

@ -0,0 +1,204 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"fmt"
"os"
"path"
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
utiltesting "k8s.io/kubernetes/pkg/util/testing"
)
var rsaCertPEM = `-----BEGIN CERTIFICATE-----
MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
-----END CERTIFICATE-----
`
var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
-----END RSA PRIVATE KEY-----
`
const mismatchRSAKeyPEM = `-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC/665h55hWD4V2
kiQ+B/G9NNfBw69eBibEhI9vWkPUyn36GO2r3HPtRE63wBfFpV486ns9DoZnnAYE
JaGjVNCCqS5tQyMBWp843o66KBrEgBpuddChigvyul33FhD1ImFnN+Vy0ajOJ+1/
Zai28zBXWbxCWEbqz7s8e2UsPlBd0Caj4gcd32yD2BwiHqzB8odToWRUT7l+pS8R
qA1BruQvtjEIrcoWVlE170ZYe7+Apm96A+WvtVRkozPynxHF8SuEiw4hAh0lXR6b
4zZz4tZVV8ev2HpffveV/68GiCyeFDbglqd4sZ/Iga/rwu7bVY/BzFApHwu2hmmV
XLnaa3uVAgMBAAECggEAG+kvnCdtPR7Wvw6z3J2VJ3oW4qQNzfPBEZVhssUC1mB4
f7W+Yt8VsOzdMdXq3yCUmvFS6OdC3rCPI21Bm5pLFKV8DgHUhm7idwfO4/3PHsKu
lV/m7odAA5Xc8oEwCCZu2e8EHHWnQgwGex+SsMCfSCTRvyhNb/qz9TDQ3uVVFL9e
9a4OKqZl/GlRspJSuXhy+RSVulw9NjeX1VRjIbhqpdXAmQNXgShA+gZSQh8T/tgv
XQYsMtg+FUDvcunJQf4OW5BY7IenYBV/GvsnJU8L7oD0wjNSAwe/iLKqV/NpYhre
QR4DsGnmoRYlUlHdHFTTJpReDjWm+vH3T756yDdFAQKBgQD2/sP5dM/aEW7Z1TgS
TG4ts1t8Rhe9escHxKZQR81dfOxBeCJMBDm6ySfR8rvyUM4VsogxBL/RhRQXsjJM
7wN08MhdiXG0J5yy/oNo8W6euD8m8Mk1UmqcZjSgV4vA7zQkvkr6DRJdybKsT9mE
jouEwev8sceS6iBpPw/+Ws8z1QKBgQDG6uYHMfMcS844xKQQWhargdN2XBzeG6TV
YXfNFstNpD84d9zIbpG/AKJF8fKrseUhXkJhkDjFGJTriD3QQsntOFaDOrHMnveV
zGzvC4OTFUUFHe0SVJ0HuLf8YCHoZ+DXEeCKCN6zBXnUue+bt3NvLOf2yN5o9kYx
SIa8O1vIwQKBgEdONXWG65qg/ceVbqKZvhUjen3eHmxtTZhIhVsX34nlzq73567a
aXArMnvB/9Bs05IgAIFmRZpPOQW+RBdByVWxTabzTwgbh3mFUJqzWKQpvNGZIf1q
1axhNUA1BfulEwCojyyxKWQ6HoLwanOCU3T4JxDEokEfpku8EPn1bWwhAoGAAN8A
eOGYHfSbB5ac3VF3rfKYmXkXy0U1uJV/r888vq9Mc5PazKnnS33WOBYyKNxTk4zV
H5ZBGWPdKxbipmnUdox7nIGCS9IaZXaKt5VGUzuRnM8fvafPNDxz2dAV9e2Wh3qV
kCUvzHrmqK7TxMvN3pvEvEju6GjDr+2QYXylD0ECgYAGK5r+y+EhtKkYFLeYReUt
znvSsWq+JCQH/cmtZLaVOldCaMRL625hSl3XPPcMIHE14xi3d4njoXWzvzPcg8L6
vNXk3GiNldACS+vwk4CwEqe5YlZRm5doD07wIdsg2zRlnKsnXNM152OwgmcchDul
rLTt0TTazzwBCgCD0Jkoqg==
-----END PRIVATE KEY-----`
func tearDown(tmpDir string) {
err := os.RemoveAll(tmpDir)
if err != nil {
fmt.Printf("Error in cleaning up test: %v", err)
}
}
func write(path, contents string, t *testing.T) {
f, err := os.Create(path)
if err != nil {
t.Fatalf("Failed to create %v.", path)
}
_, err = f.WriteString(contents)
if err != nil {
t.Fatalf("Failed to write to %v.", path)
}
}
func writeKeyPair(tmpDirPath, key, cert string, t *testing.T) (keyPath, certPath string) {
keyPath = path.Join(tmpDirPath, "tls.key")
certPath = path.Join(tmpDirPath, "tls.cert")
write(keyPath, key, t)
write(certPath, cert, t)
return
}
func TestSecretForTLSGenerate(t *testing.T) {
invalidCertTmpDir := utiltesting.MkTmpdirOrDie("tls-test")
defer tearDown(invalidCertTmpDir)
invalidKeyPath, invalidCertPath := writeKeyPair(invalidCertTmpDir, "test", "test", t)
validCertTmpDir := utiltesting.MkTmpdirOrDie("tls-test")
defer tearDown(validCertTmpDir)
validKeyPath, validCertPath := writeKeyPair(validCertTmpDir, rsaKeyPEM, rsaCertPEM, t)
mismatchCertTmpDir := utiltesting.MkTmpdirOrDie("tls-mismatch-test")
defer tearDown(mismatchCertTmpDir)
mismatchKeyPath, mismatchCertPath := writeKeyPair(mismatchCertTmpDir, mismatchRSAKeyPEM, rsaCertPEM, t)
tests := map[string]struct {
params map[string]interface{}
expected *api.Secret
expectErr bool
}{
"test-valid-tls-secret": {
params: map[string]interface{}{
"name": "foo",
"key": validKeyPath,
"cert": validCertPath,
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{
api.TLSCertKey: []byte(rsaCertPEM),
api.TLSPrivateKeyKey: []byte(rsaKeyPEM),
},
Type: api.SecretTypeTLS,
},
expectErr: false,
},
"test-invalid-key-pair": {
params: map[string]interface{}{
"name": "foo",
"key": invalidKeyPath,
"cert": invalidCertPath,
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{
api.TLSCertKey: []byte("test"),
api.TLSPrivateKeyKey: []byte("test"),
},
Type: api.SecretTypeTLS,
},
expectErr: true,
},
"test-mismatched-key-pair": {
params: map[string]interface{}{
"name": "foo",
"key": mismatchKeyPath,
"cert": mismatchCertPath,
},
expected: &api.Secret{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Data: map[string][]byte{
api.TLSCertKey: []byte(rsaCertPEM),
api.TLSPrivateKeyKey: []byte(mismatchRSAKeyPEM),
},
Type: api.SecretTypeTLS,
},
expectErr: true,
},
"test-missing-required-param": {
params: map[string]interface{}{
"name": "foo",
"key": "/tmp/foo.key",
},
expectErr: true,
},
}
generator := SecretForTLSGeneratorV1{}
for _, test := range tests {
obj, err := generator.Generate(test.params)
if !test.expectErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
if test.expectErr && err != nil {
continue
}
if !reflect.DeepEqual(obj.(*api.Secret), test.expected) {
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Secret))
}
}
}