From 37633c7266ccf9682e2e0378a5e4fe69e82a1cbe Mon Sep 17 00:00:00 2001 From: Torben Neufeldt Date: Mon, 8 Apr 2019 22:55:10 +0200 Subject: [PATCH] Provide runtime generated credentials through credentials file Add documentation for credentials file Signed-off-by: Torben Neufeldt --- README.md | 18 ++++++++++++++++++ out/assets/credentials.json | 4 ++++ out/command.go | 23 +++++++++++++++++++++-- out/command_test.go | 26 ++++++++++++++++++++++++++ out/models.go | 6 ++++++ 5 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 out/assets/credentials.json diff --git a/README.md b/README.md index f44a3b2..4fa6507 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ be specified. * `docker_password`: *Optional.* This should be the users password when authenticating against a protected docker registry. * `show_app_log`: *Optional.* Tails the app log during startup, useful to debug issues when using blue/green deploys together with the `current_app_name` option. * `no_start`: *Optional.* Deploys the app but does not start it. This parameter is ignored when `current_app_name` is specified. +* `credentials_file`: *Optional.* Reads username and password from a json file and overrides the source. This can be used to provide short-lived temporary technical users for deployment. ## Pipeline example @@ -64,6 +65,23 @@ jobs: key: value key2: value2 +- name: job-deploy-app-with-dynamic-credentials + public: true + serial: true + plan: + - get: resource-web-app + - task: build + file: resource-web-app/build.yml + - task: get-credentials + file: resource-web-app/get-credentials.yml + - put: resource-deploy-web-app + params: + credentials_file: get-credentials-output/credentials.json + manifest: build-output/manifest.yml + environment_variables: + key: value + key2: value2 + resources: - name: resource-web-app type: git diff --git a/out/assets/credentials.json b/out/assets/credentials.json new file mode 100644 index 0000000..219fdce --- /dev/null +++ b/out/assets/credentials.json @@ -0,0 +1,4 @@ +{ + "password": "hunter2", + "username": "awesome@pivotal.io" +} diff --git a/out/command.go b/out/command.go index 737197f..7d4cf26 100644 --- a/out/command.go +++ b/out/command.go @@ -1,6 +1,9 @@ package out import ( + "bytes" + "encoding/json" + "io/ioutil" "time" "os" @@ -21,10 +24,26 @@ func NewCommand(paas PAAS) *Command { } func (command *Command) Run(request Request) (Response, error) { + + var credentials Credentials + + if request.Params.CredentialsFile != "" { + rawCredentialsFile, err := ioutil.ReadFile(request.Params.CredentialsFile) + if err != nil { + return Response{}, err + } + + if err := json.NewDecoder(bytes.NewReader(rawCredentialsFile)).Decode(&credentials); err != nil { + return Response{}, err + } + } else { + credentials = Credentials{Password: request.Source.Password, Username:request.Source.Username} + } + err := command.paas.Login( request.Source.API, - request.Source.Username, - request.Source.Password, + credentials.Username, + credentials.Password, request.Source.ClientID, request.Source.ClientSecret, request.Source.SkipCertCheck, diff --git a/out/command_test.go b/out/command_test.go index 581719e..81dcfe5 100644 --- a/out/command_test.go +++ b/out/command_test.go @@ -255,6 +255,32 @@ var _ = Describe("Out Command", func() { Expect(clientSecret).To(Equal("hunter2")) }) + It("lets users authenticate with runtime provided credentials through file", func() { + request = out.Request{ + Source: resource.Source{ + API: "https://api.run.pivotal.io", + Organization: "secret", + Space: "volcano-base", + }, + Params: out.Params{ + ManifestPath: "a/path/to/a/manifest.yml", + CredentialsFile: "assets/credentials.json", + }, + } + + _, err := command.Run(request) + Expect(err).NotTo(HaveOccurred()) + + By("logging in") + Expect(cloudFoundry.LoginCallCount()).To(Equal(1)) + + _, username, password, clientID, clientSecret, _ := cloudFoundry.LoginArgsForCall(0) + Expect(username).To(Equal("awesome@pivotal.io")) + Expect(password).To(Equal("hunter2")) + Expect(clientID).To(Equal("")) + Expect(clientSecret).To(Equal("")) + }) + It("lets people do a zero downtime deploy", func() { request = out.Request{ Source: resource.Source{ diff --git a/out/models.go b/out/models.go index aa09655..6713a47 100644 --- a/out/models.go +++ b/out/models.go @@ -18,9 +18,15 @@ type Params struct { DockerPassword string `json:"docker_password"` ShowAppLog bool `json:"show_app_log"` NoStart bool `json:"no_start"` + CredentialsFile string `json:"credentials_file"` } type Response struct { Version resource.Version `json:"version"` Metadata []resource.MetadataPair `json:"metadata"` } + +type Credentials struct { + Username string `json:"username"` + Password string `json:"password"` +}