<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Armory Docs – Armory Admin</title><link>/continuous-deployment/armory-admin/</link><description>Recent content in Armory Admin on Armory Docs</description><generator>Hugo -- gohugo.io</generator><atom:link href="/continuous-deployment/armory-admin/index.xml" rel="self" type="application/rss+xml"/><item><title>Continuous-Deployment: Add a Kubernetes Account Deployment Target in Spinnaker</title><link>/continuous-deployment/armory-admin/kubernetes-account-add/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/kubernetes-account-add/</guid><description>
&lt;h2 id="how-spinnaker-operates-when-deploying-to-kubernetes-targets">How Spinnaker operates when deploying to Kubernetes targets&lt;/h2>
&lt;p>At a high level, Spinnaker operates in the following way when deploying to Kubernetes:&lt;/p>
&lt;ul>
&lt;li>Spinnaker is configured with one or more &amp;ldquo;Cloud Provider&amp;rdquo; Kubernetes accounts (which you can think of as deployment targets)&lt;/li>
&lt;li>For each Kubernetes account, Spinnaker is provided a kubeconfig to connect to that Kubernetes cluster&lt;/li>
&lt;li>The kubeconfig should have the following contents:
&lt;ul>
&lt;li>A Kubernetes kubeconfig &lt;code>cluster&lt;/code>, which is typically a URL and potentially certificate validation information (CA cert or a flag to skip validation)&lt;/li>
&lt;li>A Kubernetes kubeconfig &lt;code>user&lt;/code>, which is basically a way to get a set of credentials to connect to the Kubernetes cluster. This can be a token, a set of commands to run to get a token, or a client certificate&lt;/li>
&lt;li>A Kubernetes kubeconfig &lt;code>context&lt;/code>, which tells the &lt;code>kubectl&lt;/code> tool which credential set to use with which cluster, as well as other information such as default namespace&lt;/li>
&lt;li>Metadata such as which context to use by default&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Each Kubernetes account is configured in the &lt;code>SpinnakerService&lt;/code> manifest under &lt;code>spec.spinnakerConfig.config.providers.kubernetes.accounts&lt;/code> key if using the Operator. Each entity has these (and other) fields:
&lt;ul>
&lt;li>&lt;code>name&lt;/code>: A Spinnaker-internal name used to refer to the Kubernetes account. This is the item you will select in various Kubernetes stages to indicate that you would like to deploy to this particular Kubernetes account (which again, consists of a Kubernetes cluster/credential/context set)&lt;/li>
&lt;li>&lt;code>kubeconfigFile&lt;/code>: A file path referencing the contents of the kubeconfig file for connecting to the target cluster. When using the Operator, this can be any name that should match an entry in &lt;code>spec.spinnakerConfig.files&lt;/code> where the file contents is copied. This field supports referencing files stored in external &lt;a href="/continuous-deployment/armory-admin/secrets/">secret engines&lt;/a>&lt;/li>
&lt;li>&lt;code>onlySpinnakerManaged&lt;/code>: When &lt;code>true&lt;/code>, Spinnaker only caches and displays applications that have been created by Spinnaker. Before placing in a &lt;code>false&lt;/code> state, you should review the Kubernetes cluster configuration. When &lt;code>false&lt;/code>, Spinnaker analyzes the cluster and automatically attempts to configure and populate applications for resources already present in Kubernetes, unless limited with &lt;code>omitNamespaces&lt;/code>. You should note the &lt;a href="https://kb.armory.io/s/article/Autogenerated-Applications-Cannot-be-Deleted-w-onlySpinnakerManaged-set-to-false">increased possibilities of misconfigured Autogenerated Application Placeholders in the deployments&lt;/a>.&lt;/li>
&lt;li>&lt;code>namespaces&lt;/code>: An array of namespaces that Spinnaker will be allowed to deploy to. If this is left blank, Spinnaker will be allowed to deploy to all namespaces&lt;/li>
&lt;li>&lt;code>omitNamespaces&lt;/code>: If namespaces is left blank, you can blacklist specific namespaces to indicate to Spinnaker that it should not deploy to those namespaces&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Spinnaker uses &lt;code>kubectl&lt;/code> under the hood, so any semantics that &lt;code>kubectl&lt;/code> specifies, Spinnaker will also use&lt;/li>
&lt;li>&lt;code>kubectl&lt;/code> (and the corresponding kubeconfig) will be run from the Spinnaker Clouddriver Kubernetes pod&lt;/li>
&lt;li>If the kubeconfig is properly referenced and available, Operator will take care of the following for you:
&lt;ul>
&lt;li>Creating a Kubernetes secret (with a dynamically-generated name) containing your kubeconfig in the namespace where Spinnaker lives&lt;/li>
&lt;li>Dynamically generating a &lt;code>clouddriver.yml&lt;/code> file that properly references the kubeconfig from where it is mounted within the Clouddriver container&lt;/li>
&lt;li>Creating/Updating the Kubernetes Deployment (&lt;code>spin-clouddriver&lt;/code>) which runs Clouddriver so that it is aware of the secret and properly mounts it in the Clouddriver pod&lt;/li>
&lt;li>Creating a secret containing &lt;code>clouddriver.yml&lt;/code> (and optionally, &lt;code>clouddriver-local.yml&lt;/code>) and including it in the spin-clouddriver deployment&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>So here are some takeaways and guiding principles that result from the above:&lt;/p>
&lt;ul>
&lt;li>Spinnaker relies on the kubeconfig to authenticate against and access your Kubernetes cluster.&lt;/li>
&lt;li>You can use a command-based or auth-provider-based kubeconfig user (such as &lt;code>aws-iam-authenticator&lt;/code>), but this will rely on the command binary and all relevant files existing in the Clouddriver, and all authentication (such as IAM roles) being properly attached to the Clouddriver container.&lt;/li>
&lt;li>Alternately (and perhaps, preferably), you can do the following:
&lt;ul>
&lt;li>Create a Kubernetes service account in your Kubernetes cluster. This service account will exist in some specific namespace.&lt;/li>
&lt;li>Grant the service account permissions on your cluster. This can be one or more of the following:
&lt;ul>
&lt;li>&lt;code>cluster-admin&lt;/code> access, to be able to access all namespaces in your cluster&lt;/li>
&lt;li>Full wildcard (apiGroup &lt;code>*&lt;/code> / resource &lt;code>*&lt;/code> / verb &lt;code>*&lt;/code>) access to one or more namespaces in your cluster&lt;/li>
&lt;li>More specific permissions in your cluster (this is not covered in the scope of this document)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>It is preferable to create a distinct kubeconfig file for each Spinnaker Cloud Provider Kubernetes account; each of these kubeconfigs should have &lt;strong>one&lt;/strong> cluster, &lt;strong>one&lt;/strong> user, and &lt;strong>one&lt;/strong> context referencing the cluster and user. Its default context should reference the single context&lt;/li>
&lt;/ul>
&lt;h2 id="before-you-begin">Before you begin&lt;/h2>
&lt;p>This document assumes the following:&lt;/p>
&lt;ul>
&lt;li>Your Armory CD or Spinnaker instance is running&lt;/li>
&lt;li>If using Spinnaker, you installed and configured Spinnaker using Armory&amp;rsquo;s Spinnaker Operator. You have access to the &lt;code>SpinnakerService&lt;/code> manifest and have the kubeconfig for the Spinnaker cluster.&lt;/li>
&lt;li>You have a valid kubeconfig that currently has Cluster Admin access to your target Kubernetes cluster so you can create the relevant Kubernetes entities (&lt;code>service account&lt;/code>, &lt;code>role&lt;/code>, and &lt;code>rolebinding&lt;/code>) in the target cluster; you have &lt;code>kubectl&lt;/code> and are able to use it to interact with your target Kubernetes cluster.&lt;/li>
&lt;/ul>
&lt;p>The first several steps of this document take place on a system that has &lt;code>kubectl&lt;/code> and the kubeconfig.&lt;/p>
&lt;h2 id="workflow-for-adding-a-kubernetes-service-account">Workflow for adding a Kubernetes Service Account&lt;/h2>
&lt;ul>
&lt;li>Create the namespace in which the Service Account will live (if it does not yet exist)&lt;/li>
&lt;li>Create the service account in the Service Account namespace&lt;/li>
&lt;li>If granting cluster admin (&lt;code>cluster-admin&lt;/code>), a &lt;code>clusterrolebinding&lt;/code> attaching the &lt;code>cluster-admin&lt;/code> ClusterRole to the service account&lt;/li>
&lt;li>If granting namespace-specific access, the following:
&lt;ul>
&lt;li>For each namespace, the namespace (if it does not exist)&lt;/li>
&lt;li>For each target namespace, an admin role&lt;/li>
&lt;li>For each target namespace, a rolebinding attaching the admin role to the service account&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Create a minified kubeconfig containing only the service account&lt;/li>
&lt;li>Add the account to Spinnaker&lt;/li>
&lt;/ul>
&lt;h2 id="setting-up-the-kubernetes-service-account">Setting up the Kubernetes Service Account&lt;/h2>
&lt;p>In this section, you create the following:&lt;/p>
&lt;ul>
&lt;li>A namespace to create the service account in&lt;/li>
&lt;li>A service account in that namespace&lt;/li>
&lt;li>A role and rolebinding in that namespace, granting permissions to the service account&lt;/li>
&lt;li>A kubeconfig containing credentials for the service account&lt;/li>
&lt;/ul>
&lt;p>This document uses the newly-created Armory &lt;code>spinnaker-tools&lt;/code> Go CLI (available on &lt;a href="https://github.com/armory/spinnaker-tools">Github&lt;/a>) to create many of these resources. There are separate instructions to perform these steps manually.&lt;/p>
&lt;h3 id="download-the-latest-spinnaker-tools-release">Download the latest &lt;code>spinnaker-tools&lt;/code> release&lt;/h3>
&lt;p>Go to &lt;a href="https://github.com/armory/spinnaker-tools/releases">https://github.com/armory/spinnaker-tools/releases&lt;/a> to download the latest release for your operating system (OSX and Linux available). You can also use curl:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># If you&amp;#39;re not already in the directory&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">cd&lt;/span> ~/eks-spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Replace this with the correct version and link for your workstation (use https://github.com/armory/spinnaker-tools/releases/download/latest/spinnaker-tools-linux if you&amp;#39;re on Linux instead of Mac)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl -L https://github.com/armory/spinnaker-tools/releases/download/latest/spinnaker-tools-darwin -o spinnaker-tools
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>chmod +x spinnaker-tools
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="set-up-bash-parameters">Set up bash parameters&lt;/h3>
&lt;p>Set up bash environment variables that you will use later.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># If you&amp;#39;re using a different source kubeconfig, specify it here&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">export&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">SOURCE_KUBECONFIG&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">HOME&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>/.kube/config
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Specify the name of the kubernetes context that has permissions in your target cluster.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># To get context names, you can run &amp;#34;kubectl config get-contexts&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">export&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;aws-armory-dev&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Enter the namespace where you want the Spinnaker service account to live&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">export&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">SPINNAKER_NAMESPACE&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;spinnaker-system&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Enter the name of the service account you want to create in the target namespace.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># If you are creating multiple Kubernetes Cloud Provider Accounts to point to&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># different namespaces in to the same Kubernetes cluster, make sure you use a&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># unique service account name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">export&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">SPINNAKER_SERVICE_ACCOUNT_NAME&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;spinnaker-dev-sa&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Specify where you want the new kubeconfig to be created&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">export&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">DEST_KUBECONFIG&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">PWD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>/kubeconfig-dev-sa
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># If you want to deploy to a specific set of namespaces, enter the namespaces&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># that you want to deploy to (space-delimited).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># These namespaces can already exist, or you can create them.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">export&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">TARGET_NAMESPACES_COMMA_SEPARATED&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>dev-1,dev-2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="option-1-create-the-service-account-with-cluster-admin-permissions">Option 1: Create the service account with cluster-admin permissions&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./spinnaker-tools create-service-account &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SOURCE_KUBECONFIG&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --output &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">DEST_KUBECONFIG&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --namespace &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SPINNAKER_NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --service-account-name &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SPINNAKER_SERVICE_ACCOUNT_NAME&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;div class="alert alert-warning" role="alert">
&lt;h4 class="alert-heading">Important&lt;/h4>
For Kubernetes v1.24+, service account tokens are no longer generated when you execute this script. See the &lt;code>LegacyServiceAccountTokenNoAutoGeneration&lt;/code> entry in Kubernetes 1.24&amp;rsquo;s &lt;a href="LegacyServiceAccountTokenNoAutoGeneration">Urgent Upgrade Notes&lt;/a> for details and the new process to follow for creating service account tokens.
&lt;/div>
&lt;h3 id="option-2-create-the-service-account-with-namespace-specific-permissions">Option 2: Create the service account with namespace-specific permissions&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./spinnaker-tools create-service-account &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SOURCE_KUBECONFIG&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --output &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">DEST_KUBECONFIG&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --namespace &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SPINNAKER_NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --service-account-name &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SPINNAKER_SERVICE_ACCOUNT_NAME&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --target-namespaces &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">TARGET_NAMESPACES_COMMA_SEPARATED&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="add-the-kubeconfig-and-cloud-provider-to-spinnaker">Add the kubeconfig and cloud provider to Spinnaker&lt;/h2>
&lt;p>Add the following configuration to the &lt;code>SpinnakerServce&lt;/code> manifest, replacing values as needed:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">providers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kubernetes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-dev &lt;span style="color:#6272a4"># Account name you want Spinnaker to use to identify the deployment target&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">requiredGroupMembership&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">providerVersion&lt;/span>: V2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">permissions&lt;/span>: {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dockerRegistries&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">configureImagePullSecrets&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cacheThreads&lt;/span>: &lt;span style="color:#bd93f9">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">namespaces&lt;/span>: [] &lt;span style="color:#6272a4"># Change if you only want to deploy to specific namespaces&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">omitNamespaces&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kinds&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">omitKinds&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">customResources&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cachingPolicies&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">oAuthScopes&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">onlySpinnakerManaged&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kubeconfigFile&lt;/span>: kubeconfig-spinnaker-dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">primaryAccount&lt;/span>: spinnaker-dev &lt;span style="color:#6272a4"># Change to a desired account from the accounts array&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">features&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">artifacts&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span> &lt;span style="color:#6272a4"># Not strictly necessary for Kubernetes but will be useful in general&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">files&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kubeconfig-spinnaker-dev&lt;/span>: |&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &lt;/span> &amp;lt;FILE CONTENTS HERE&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, apply the changes&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest file&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="verify-the-kubernetes-account-appears-in-the-spinnaker-ui">Verify the Kubernetes account appears in the Spinnaker UI&lt;/h2>
&lt;p>After you apply your changes, you should see the new Kubernetes account in your Spinnaker UI and be able to deploy to it. It may take a while for the Clouddriver to start up and read information from your new Kubernetes account.&lt;/p>
&lt;blockquote>
&lt;p>Don&amp;rsquo;t forget to clear your browser cache / hard refresh your browser (&lt;code>cmd-shift-r&lt;/code> or &lt;code>control-shift-r&lt;/code>)&lt;/p>
&lt;/blockquote></description></item><item><title>Continuous-Deployment: Administration for Cloud Foundry</title><link>/continuous-deployment/armory-admin/cf/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/cf/</guid><description/></item><item><title>Continuous-Deployment: Administration on AWS</title><link>/continuous-deployment/armory-admin/aws/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/aws/</guid><description/></item><item><title>Continuous-Deployment: Auth Propagation in Spinnaker Pipelines</title><link>/continuous-deployment/armory-admin/authorization/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/authorization/</guid><description>
&lt;h2 id="overview-of-authentication-and-authorization-in-spinnaker">Overview of Authentication and Authorization in Spinnaker&lt;/h2>
&lt;p>Both Armory Continuous Deployment and Spinnaker&lt;sup>TM&lt;/sup> provide the same functionality for authentication (&amp;ldquo;authn&amp;rdquo;)
and authorization (&amp;ldquo;authz&amp;rdquo;). You can find a full reference of how to set up both in the &lt;a href="https://www.spinnaker.io/setup/security/#security">Spinnaker documentation&lt;/a>.&lt;/p>
&lt;h2 id="authorization-amp-manual-judgments">Authorization &amp;amp; Manual Judgments&lt;/h2>
&lt;p>The &lt;a href="https://www.spinnaker.io/setup/security/authorization/#restrictable-resources">Spinnaker docs&lt;/a> explain that you can limit users&amp;rsquo; access to both
&amp;ldquo;accounts&amp;rdquo; and &amp;ldquo;applications&amp;rdquo; but doesn&amp;rsquo;t talk much about the interaction of
the two.&lt;/p>
&lt;p>In short, if you have access to an application, you can view the pipelines,
and kick off a manual execution (even if you have &amp;ldquo;read only&amp;rdquo; access).
However, if those pipelines need to do something in your cloud environments,
you will still need to have read/write access to those environments. Since
the pipeline will run its stages &amp;ldquo;as the user&amp;rdquo; that initiated the pipeline,
the stages that attempt to write changes to the environment will fail if that
user doesn&amp;rsquo;t have access to those environments.&lt;/p>
&lt;p>There is one exception to this rule, and that is for Manual Judgment stages.
You can configure a Manual Judgment stage to &amp;ldquo;Propagate Authentication&amp;rdquo;:&lt;/p>
&lt;figure>
&lt;img src="/images/Image-2018-10-16-at-10.05.04-AM.png"/>
&lt;/figure>
&lt;p>Checking this box will cause the pipeline to use the identity and
authorizations of the user who approved the stage for all
subsequent stages. By inserting a Manual Judgment stage with this option
enabled into your pipeline before the actual deploy, you can allow users
with limited access to kick off pipelines safely; a user &lt;em>with&lt;/em> full access
to the environment can then continue the pipeline successfully after approval.&lt;/p></description></item><item><title>Continuous-Deployment: Bake and Share Amazon Machine Images Across Accounts</title><link>/continuous-deployment/armory-admin/bake-and-share/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/bake-and-share/</guid><description>
&lt;h2 id="overview-of-sharing-amis-across-accounts">Overview of sharing AMIs across accounts&lt;/h2>
&lt;p>In many environments, Spinnaker&lt;sup>TM&lt;/sup> runs under a different AWS account than the target deployment account. This guide shows you how to configure Spinnaker to share an AMI created where Spinnaker lives with the AWS account where your applications live. This guide is assuming that AWS roles are already properly setup for talking to the target account.&lt;/p>
&lt;h2 id="spinnaker-configuration-for-sharing-baked-amis">Spinnaker configuration for sharing baked AMIs&lt;/h2>
&lt;p>You can add the following snippet to your &lt;code>SpinnakerService&lt;/code> manifest and apply it after replacing the example values with ones that correspond to your environment. The example adds an AWS account and configures the baking service (Rosco) with default values:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">aws&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: my-aws-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">requiredGroupMembership&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">providerVersion&lt;/span>: V1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">permissions&lt;/span>: {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accountId&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#39;aws-account-id&amp;#39;&lt;/span> &lt;span style="color:#6272a4"># Use your AWS account id&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">regions&lt;/span>: &lt;span style="color:#6272a4"># Specify all target regions for deploying applications&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: us-west-2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">assumeRole&lt;/span>: role/SpinnakerManagedProfile &lt;span style="color:#6272a4"># Role name that worker nodes of Spinnaker cluster caassume in the target account to make deployments and scan infrastructure&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">primaryAccount&lt;/span>: my-aws-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">bakeryDefaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseImages&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaultKeyPairTemplate&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#39;{{&amp;#34;{{&amp;#34;}}name{{&amp;#34;}}&amp;#34;}}-keypair&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaultRegions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: us-west-2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">iamRole&lt;/span>: BaseIAMRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ... &lt;span style="color:#6272a4"># Config omitted for brevity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">service-settings&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rosco&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">env&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">SPINNAKER_AWS_DEFAULT_REGION&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;us-west-2&amp;#34;&lt;/span> &lt;span style="color:#6272a4"># Replace by default bake region&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">SPINNAKER_AWS_DEFAULT_ACCOUNT&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;target-aws-account-id&amp;#34;&lt;/span> &lt;span style="color:#6272a4"># Target AWS account id&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ... &lt;span style="color:#6272a4"># Config omitted for brevity&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="spinnaker-pipeline-bake-stage-configuration">Spinnaker pipeline Bake stage configuration&lt;/h2>
&lt;figure>
&lt;img src="/images/bake-and-share-1.png"/>
&lt;/figure>
&lt;p>Make sure to check the &lt;code>Show Advanced Options&lt;/code> checkbox. Then where it says &lt;code>Template File Name&lt;/code> use &lt;a href="https://github.com/spinnaker/rosco/blob/ccb004e511b14642218aaf229923fefa0a9c250c/rosco-web/config/packer/aws-multi-ebs.json">aws-multi-ebs.json&lt;/a> as the value.&lt;/p>
&lt;p>Then add an &lt;code>Extended Attribute&lt;/code>. Have the key be &lt;code>share_with_1&lt;/code> and the value being the target AWS account ID that was used for &lt;code>SPINNAKER_AWS_DEFAULT_ACCOUNT&lt;/code>. &lt;code>share_with_1&lt;/code> is for &lt;a href="https://www.packer.io/docs/builders/amazon-ebs.html#ami_users">ami_users&lt;/a> inside Packer.&lt;/p>
&lt;p>You can also copy the resulting AMI to different regions by overriding the &lt;a href="https://github.com/spinnaker/rosco/blob/ccb004e511b14642218aaf229923fefa0a9c250c/rosco-web/config/packer/aws-multi-ebs.json#L33">copy_to_1&lt;/a> values. These match up to &lt;a href="https://www.packer.io/docs/builders/amazon-instance.html#ami_regions">ami_regions&lt;/a> inside Packer.&lt;/p></description></item><item><title>Continuous-Deployment: Clouddriver Caching Agents in Spinnaker</title><link>/continuous-deployment/armory-admin/caching-agents-concept/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/caching-agents-concept/</guid><description>
&lt;h2 id="how-spinnaker-discovers-and-caches-infrastructure-elements">How Spinnaker discovers and caches infrastructure elements&lt;/h2>
&lt;p>Clouddriver is the Spinnaker™ service responsible for discovering and caching cloud provider infrastructure, such as AWS EC2 instances, Kubernetes pods, and Docker images. Clouddriver has a &lt;a href="#the-caching-agent-scheduler">caching agent scheduler&lt;/a> that runs caching agents for providers in separate threads at scheduled intervals. These agents query the infrastructure, index the data, and save the results in a &lt;a href="#the-cache-store">cache store&lt;/a>, which is usually a Redis or a SQL datastore.&lt;/p>
&lt;h2 id="the-caching-agent">The caching agent&lt;/h2>
&lt;figure>
&lt;img src="/images/armory-admin/clouddriver/caching-agents.png"
alt="Clouddriver providers and caching agents architecture" width="618" height="207"/> &lt;figcaption>
&lt;p>&lt;i>Clouddriver providers and caching agents architecture&lt;/i>&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>Caching agents query your cloud infrastructure for resources and store the results in a cache store. Each provider has its own set of caching agents that Spinnaker instantiates per account and, sometimes, per region. Each caching agent specializes in one type of resource, such as server groups, load balancers, security groups, or instances.&lt;/p>
&lt;p>The number of caching agents varies greatly between providers and Clouddriver configurations. For example, AWS might have between 16 and 20 agents per region performing tasks such as caching the status of IAM roles, instances, and VPCs. AWS might also have some agents operating globally for tasks like cleaning up detached instances. Kubernetes, on the other hand, might have a few agents per cluster, caching things like custom resources and Kubernetes manifests.&lt;/p>
&lt;h2 id="the-cache-store">The cache store&lt;/h2>
&lt;p>The cache store is where Clouddriver stores cloud resources. You can use different types:&lt;/p>
&lt;ul>
&lt;li>Redis - the default and most popular implementation.&lt;/li>
&lt;li>SQL - recommended store. For how to configure Clouddriver to use SQL, see the &lt;a href="/continuous-deployment/armory-admin/clouddriver-sql-configure/"}>Configure Clouddriver to use a SQL Database&lt;/a>.&lt;/li>
&lt;li>an in-memory cache that is not used for actual Spinnaker deployments.&lt;/li>
&lt;/ul>
&lt;p>With the exception of the in-memory store, these stores work across multiple Clouddriver instances.&lt;/p>
&lt;p>One or more instances of Clouddriver update this single cache store.&lt;/p>
&lt;h2 id="the-caching-agent-scheduler">The caching agent scheduler&lt;/h2>
&lt;p>The caching agent scheduler runs caching agents at regular intervals across all Clouddriver instances. There are multiple types of schedulers:&lt;/p>
&lt;ul>
&lt;li>the Redis-backed scheduler that locks agents by reading/writing a key to Redis.&lt;/li>
&lt;li>the Redis-backed sort scheduler that locks agents by reading/writing a key to Redis &lt;em>and&lt;/em> manages the order of agents being executed.&lt;/li>
&lt;li>the SQL-backed scheduler that locks agents by inserting a row in a table with a unique constraint - not very efficient, prefer other schedulers.&lt;/li>
&lt;li>the default scheduler that doesn&amp;rsquo;t lock. Don&amp;rsquo;t use this if you expect to run more than one Clouddriver instance.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>The cache store does not dictate the type of agent scheduler. For instance, you could use the SQL cache store along with the Redis-backed scheduler.&lt;/p>
&lt;/blockquote>
&lt;p>If you read the Clouddriver &lt;a href="https://github.com/spinnaker/clouddriver">source code&lt;/a>, you see references to &lt;code>cats&lt;/code> (&lt;em>Cache All The Stuff&lt;/em>), which is the framework that manages agent scheduler, agents, and cache store.&lt;/p>
&lt;h2 id="how-the-cache-store-scheduler-and-agent-work-together">How the cache store, scheduler, and agent work together&lt;/h2>
&lt;p>When Clouddriver starts, it inspects its configuration and instantiates the cache store and the agent scheduler. For each provider enabled, Clouddriver instantiates agents per account and region and then adds them to the scheduler.&lt;/p>
&lt;p>When the scheduler runs, Clouddriver contacts agents not currently running on its own instance. The scheduler attempts to obtain a lock on the agent type/account/region to ensure that only a single Clouddriver instance caches a given resource at any given time. If Clouddriver obtains a lock, the agent is then run in a separate thread. When the agent finishes, Clouddriver updates the lock Time To Live (TTL) to match the next desired execution time.&lt;/p>
&lt;h2 id="on-demand-caching-agents">On-demand caching agents&lt;/h2>
&lt;p>Most cloud mutating operations are not synchronous. For example, when Clouddriver sends a request to AWS to launch a new EC2 instance, the API call returns successfully but the EC2 instance takes a while to be ready. This is when Spinnaker uses on-demand caching agents.&lt;/p>
&lt;p>On-demand caching agents are, as their name implies, created on demand by the client (Orca) in tasks such as &lt;code>Force Cache Refresh&lt;/code> or &lt;code>Wait for Up Instances&lt;/code>. They are used to ensure cache freshness and keep things up to date when a resource is created or effectively deleted.&lt;/p>
&lt;p>When using a cache store like Redis that works across multiple Clouddriver instances, Clouddriver waits for the next regular caching agent of the same type to run before declaring the cache consistent. It gives the cache store one more chance to replicate its state to other replicas in the case of Redis.&lt;/p>
&lt;h2 id="next-steps">Next steps&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="/continuous-deployment/armory-admin/caching-agents-config/"}>Configure Clouddriver Caching Agents in Spinnaker&lt;/a>&lt;/li>
&lt;li>If you are using Kubernetes and would like to use a different method for cataloging your Kubernetes infrastructure, see &lt;a href="/plugins/scale-agent/"}>Scale Agent for Spinnaker and Kubernetes&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>Continuous-Deployment: Configure Clouddriver Caching Agents in Spinnaker</title><link>/continuous-deployment/armory-admin/caching-agents-config/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/caching-agents-config/</guid><description>
&lt;h2 id="caching-agents-in-spinnaker">Caching agents in Spinnaker&lt;/h2>
&lt;p>See the &lt;a href="/continuous-deployment/armory-admin/caching-agents-concept/"}>Clouddriver Caching Agents in Spinnaker&lt;/a> page for detailed content on caching agents.&lt;/p>
&lt;p>Depending on how large your infrastructure is and how many elements it has, you may need to increase Clouddriver&amp;rsquo;s CPU and memory limits, increase the number of running Clouddriver instances, or both.&lt;/p>
&lt;p>The following configuration settings affect the behavior of the caching agents and can be used to adjust them depending on the size of the infrastructure being cached. If using the Spinnaker Operator, these settings live under the key &lt;code>.spec.spinnakerConfig.profiles.clouddriver&lt;/code> of &lt;code>SpinnakerService&lt;/code> manifest.&lt;/p>
&lt;h3 id="sql-global-caching-agents-configuration">SQL global caching agents configuration&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Key&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Default Value&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>sql.scheduler.enabled&lt;/code>&lt;/td>
&lt;td>Enable or disable the sql scheduler&lt;/td>
&lt;td>false&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.max-concurrent-agents&lt;/code>&lt;/td>
&lt;td>Indicates the maximum amount of agents to run at the same time when using the sql scheduler&lt;/td>
&lt;td>100&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.disabled-agents&lt;/code>&lt;/td>
&lt;td>List of agent names to disable from running&lt;/td>
&lt;td>(empty)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.enabled-pattern&lt;/code>&lt;/td>
&lt;td>Regex of agent names enabled for running&lt;/td>
&lt;td>.*&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.release-threshold-ms&lt;/code>&lt;/td>
&lt;td>Maximum amount of time for releasing agent locks after they finish running. If this value is higher than agent&amp;rsquo;s execution cycle, the agents keep running immediately after finishing&lt;/td>
&lt;td>500&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.agent-lock-acquisition-interval-seconds&lt;/code>&lt;/td>
&lt;td>How often the scheduler checks for the next batch of agents to run&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.poll.interval-seconds&lt;/code>&lt;/td>
&lt;td>Default time for how often to run caching agents&lt;/td>
&lt;td>30&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.poll.error-interval-seconds&lt;/code>&lt;/td>
&lt;td>Default time for when to run caching agents after an execution fails&lt;/td>
&lt;td>30&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>sql.agent.poll.timeout-seconds&lt;/code>&lt;/td>
&lt;td>Maximum time to hold a lock of an agent execution. If an agent takes longer to finish than this, it&amp;rsquo;s possible to have concurrent executions of the same agent&lt;/td>
&lt;td>300&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>See the &lt;a href="/continuous-deployment/armory-admin/clouddriver-sql-configure/"}>Configure Clouddriver to use a SQL Database&lt;/a> page for how to configure Clouddriver.&lt;/p>
&lt;h3 id="redis-global-caching-agents-configuration">Redis global caching agents configuration&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Key&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Default Value&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>redis.scheduler.enabled&lt;/code>&lt;/td>
&lt;td>Enable or disable the redis scheduler&lt;/td>
&lt;td>true&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis.agent.max-concurrent-agents&lt;/code>&lt;/td>
&lt;td>Indicates the maximum amount of agents to run at the same time when using the redis scheduler&lt;/td>
&lt;td>1000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis.agent.enabled-pattern&lt;/code>&lt;/td>
&lt;td>Regex of agent names enabled for running&lt;/td>
&lt;td>.*&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis.agent.agent-lock-acquisition-interval-seconds&lt;/code>&lt;/td>
&lt;td>How often the scheduler checks for the next batch of agents to run&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis.poll.interval-seconds&lt;/code>&lt;/td>
&lt;td>Default time for how often to run caching agents&lt;/td>
&lt;td>30&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis.poll.error-interval-seconds&lt;/code>&lt;/td>
&lt;td>Default time for when to run caching agents after an execution fails&lt;/td>
&lt;td>30&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>redis.poll.timeout-seconds&lt;/code>&lt;/td>
&lt;td>Maximum time to hold a lock of an agent execution. If an agent takes longer to finish that this, it&amp;rsquo;s possible to have concurrent executions of the same agent&lt;/td>
&lt;td>300&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="considerations">Considerations&lt;/h2>
&lt;ul>
&lt;li>Using the SQL scheduler has &lt;a href="https://github.com/spinnaker/spinnaker/issues/5829">known issues&lt;/a> where some agents may not be running in some versions of Spinnaker.&lt;/li>
&lt;li>The setting for &lt;code>max-concurrent-agents&lt;/code> is directly correlated with how much CPU and memory Clouddriver needs to cache infrastructure. Higher values make each replica consume more resources. Higher values also make it possible for Clouddriver to reduce the time spent caching all infrastructure.&lt;/li>
&lt;/ul></description></item><item><title>Continuous-Deployment: Configure Automated Canary Deployments in Spinnaker</title><link>/continuous-deployment/armory-admin/kayenta-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/kayenta-configure/</guid><description>
&lt;h2 id="kayenta-overview">Kayenta Overview&lt;/h2>
&lt;p>Kayenta is the Spinnaker service that performs automated canary analysis. The goal of Kayenta is to provide you with confidence that a deployment is safe through automation and intelligence.&lt;/p>
&lt;h2 id="enable-kayenta">Enable Kayenta&lt;/h2>
&lt;p>Add the following to your &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">canary&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span> &lt;span style="color:#6272a4"># Enable/disable canary analysis&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="configure-kayenta">Configure Kayenta&lt;/h2>
&lt;p>The following example is a &lt;code>SpinnakerService&lt;/code> manifest. The example config uses Datadog as the metrics provider and stores canary configs and analysis in a GCS bucket:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiversion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">canary&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span> &lt;span style="color:#6272a4"># Enable/disable canary analysis&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">serviceIntegrations&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: datadog
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: test-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">endpoint&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: &amp;lt;some-URL&amp;gt; &lt;span style="color:#6272a4"># The base URL to the Datadog server.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiKey&lt;/span>: &amp;lt;encrypted-secret&amp;gt; &lt;span style="color:#6272a4"># Your org’s unique Datadog API key. See https://app.datadoghq.com/account/settings#api. Supports encrypted value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">applicationKey&lt;/span>: &amp;lt;encrypted-secret&amp;gt; &lt;span style="color:#6272a4">#Your Datadog application key. See https://app.datadoghq.com/account/settings#api. Supports encrypted value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">supportedTypes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - METRICS_STORE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - CONFIGURATION_STORE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - OBJECT_STORE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: google
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span> &lt;span style="color:#6272a4"># Enable/disable Google provider&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: my-google-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">project&lt;/span>: my-project-id &lt;span style="color:#6272a4"># The Google Cloud Platform project the Canary service uses to consume GCS and Stackdriver.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jsonPath&lt;/span>: gcp-sa.json &lt;span style="color:#6272a4"># File name of a JSON service account that Spinnaker uses for credentials. This is only needed if Spinnaker is not deployed on a Google Compute Engine VM or needs permissions not afforded to the VM it is running on. See https://cloud.google.com/compute/docs/access/service-accounts for more information. This field supports using &amp;#34;encryptedFile&amp;#34; secret references.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">bucket&lt;/span>: my-bucket &lt;span style="color:#6272a4"># The name of a storage bucket that your specified account has access to. If you specify a globally unique bucket name that doesn&amp;#39;t exist, Kayenta creates that bucket.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">bucketLocation&lt;/span>: us-central-1 &lt;span style="color:#6272a4"># Required if the bucket you specify doesn&amp;#39;t exist. In that case, the bucket gets created in that location. See https://cloud.google.com/storage/docs/managing-buckets#manage-class-location.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rootFolder: kayenta # The root folder in the chosen bucket to place all of the Canary service&amp;#39;s persistent data in (Default&lt;/span>: kayenta).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">supportedTypes: # Array of&lt;/span>: METRICS_STORE, CONFIGURATION_STORE, OBJECT_STORE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - CONFIGURATION_STORE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - OBJECT_STORE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">gcsEnabled: true # Whether or not GCS is enabled as a persistent store (Default&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">stackdriverEnabled: false # Whether or not Stackdriver is enabled Stackdriver as a metrics service (Default&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">metadataCachingIntervalMS: 60000 # Number of milliseconds to wait between caching the names of available metric types for use in building canary configs. (Default&lt;/span>: &lt;span style="color:#bd93f9">60000&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">reduxLoggerEnabled: true # Whether or not to enable redux logging in the canary module in deck (Default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaultJudge: NetflixACAJudge-v1.0 # Name of canary judge to use by default (Default&lt;/span>: NetflixACAJudge-v1.0).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">stagesEnabled: true # Whether or not to enable canary stages in deck (Default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">templatesEnabled: true # Whether or not to enable custom filter templates for canary configs in deck (Default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">showAllConfigsEnabled: true # Whether or not to show all canary configs in deck, or just those scoped to the current application (Default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ... &lt;span style="color:#6272a4"># rest of config omitted for brevity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">files&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">gcp-sa.json&lt;/span>: |&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &lt;/span> &amp;lt;JSON CONTENT HERE. WATCH YOUR SPACING&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For an overview of how to configure metrics providers see &lt;a href="/continuous-deployment/installation/armory-operator/op-manifest-reference/canary-op-config/">Canary Config&lt;/a>. For Dynatrace and AWS Cloudwatch providers, see &lt;a href="/continuous-deployment/spinnaker-user-guides/canary/kayenta-canary-dynatrace/">Use Canary Analysis with Dynatrace&lt;/a> or &lt;a href="/plugins/aws-cloudwatch/overview/">AWS CloudWatch Integration Plugin&lt;/a>.&lt;/p>
&lt;h2 id="whats-next">What&amp;rsquo;s next&lt;/h2>
&lt;p>For information about how to use canary deployments, see &lt;a href="/continuous-deployment/spinnaker-user-guides/canary/kayenta-canary-use/"}>Use Automatic Canary Analysis in Spinnaker&lt;/a>.&lt;/p></description></item><item><title>Continuous-Deployment: Configure Clouddriver to use a SQL Database</title><link>/continuous-deployment/armory-admin/clouddriver-sql-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/clouddriver-sql-configure/</guid><description>
&lt;h2 id="advantages-of-using-an-rdms-with-clouddriver">Advantages of using an RDMS with Clouddriver&lt;/h2>
&lt;p>Since Armory Continuous Deployment version 2.5.x (Spinnaker 1.14.x), Clouddriver can store its data (task, infrastructure, etc) in a MySQL-compatible database. Similar to Orca, the main advantage of doing this is to improve performance and remove Redis as a single point of failure.&lt;/p>
&lt;p>Database compatibility:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">MySQL&lt;/th>
&lt;th style="text-align:left">PostgreSQL&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">5.7; AWS Aurora&lt;/td>
&lt;td style="text-align:left">10&amp;#43;&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Armory recommends MySQL 5.7 or AWS Aurora.&lt;/p>
&lt;h2 id="base-configuration">Base configuration&lt;/h2>
&lt;p>You can find a complete description of the options in the &lt;a href="https://www.spinnaker.io/setup/productionize/persistence/clouddriver-sql/">open source documentation&lt;/a>.&lt;/p>
&lt;h2 id="database-setup">Database setup&lt;/h2>
&lt;p>You can skip this step if you create the database during provisioning - for instance with Terraform.&lt;/p>
&lt;p>Once you&amp;rsquo;ve provisioned your RDBMS and ensured connectivity with Spinnaker, you need to create the database:&lt;/p>
&lt;blockquote>
&lt;p>Configure the RDBMS driver exactly as described in &lt;a href="https://spinnaker.io/docs/setup/productionize/persistence/clouddriver-sql/#database-setup">Set up Clouddriver to use SQL - Database Setup&lt;/a>. The MySQL database schema must be configured to with:&lt;/p>
&lt;/blockquote>
&lt;ul>
&lt;li>Default character set &lt;code>utfmb4&lt;/code>&lt;/li>
&lt;li>Default collate &lt;code>utf8mb4_unicode_ci&lt;/code>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">CREATE&lt;/span> &lt;span style="color:#ff79c6">SCHEMA&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>clouddriver&lt;span style="color:#ff79c6">`&lt;/span> &lt;span style="color:#ff79c6">DEFAULT&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">CHARACTER&lt;/span> &lt;span style="color:#ff79c6">SET&lt;/span> utf8mb4 &lt;span style="color:#ff79c6">COLLATE&lt;/span> utf8mb4_unicode_ci;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then we&amp;rsquo;ll grant authorization to the &lt;code>clouddriver_service&lt;/code> and &lt;code>clouddriver_migrate&lt;/code> users:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">GRANT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">SELECT&lt;/span>, &lt;span style="color:#ff79c6">INSERT&lt;/span>, &lt;span style="color:#ff79c6">UPDATE&lt;/span>, &lt;span style="color:#ff79c6">DELETE&lt;/span>, &lt;span style="color:#ff79c6">CREATE&lt;/span>, &lt;span style="color:#ff79c6">EXECUTE&lt;/span>, &lt;span style="color:#ff79c6">SHOW&lt;/span> &lt;span style="color:#ff79c6">VIEW&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ON&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>clouddriver&lt;span style="color:#ff79c6">`&lt;/span>.&lt;span style="color:#ff79c6">*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">TO&lt;/span> &lt;span style="color:#f1fa8c">&amp;#39;clouddriver_service&amp;#39;&lt;/span>&lt;span style="color:#ff79c6">@&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;%&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">GRANT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">SELECT&lt;/span>, &lt;span style="color:#ff79c6">INSERT&lt;/span>, &lt;span style="color:#ff79c6">UPDATE&lt;/span>, &lt;span style="color:#ff79c6">DELETE&lt;/span>, &lt;span style="color:#ff79c6">CREATE&lt;/span>, &lt;span style="color:#ff79c6">DROP&lt;/span>, &lt;span style="color:#ff79c6">REFERENCES&lt;/span>, &lt;span style="color:#ff79c6">INDEX&lt;/span>, &lt;span style="color:#ff79c6">ALTER&lt;/span>, &lt;span style="color:#ff79c6">LOCK&lt;/span> TABLES, &lt;span style="color:#ff79c6">EXECUTE&lt;/span>, &lt;span style="color:#ff79c6">SHOW&lt;/span> &lt;span style="color:#ff79c6">VIEW&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ON&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>clouddriver&lt;span style="color:#ff79c6">`&lt;/span>.&lt;span style="color:#ff79c6">*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">TO&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>clouddriver_migrate&lt;span style="color:#ff79c6">`@&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;%&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This configuration grants authorization from any host. You can restrict it to the cluster in which Spinnaker runs by replacing the &lt;code>%&lt;/code> with the IP address of Clouddriver pods from MySQL.&lt;/p>
&lt;blockquote>
&lt;p>Depending on your TLS settings, you may need to configure TLS 1.2. For more information, see the Knowledge Base articles &lt;a href="https://support.armory.io/support?sys_kb_id=6d38e4bfdba47c1079f53ec8f49619c2&amp;amp;id=kb_article_view&amp;amp;sysparm_rank=2&amp;amp;sysparm_tsqueryId=f93349771b3d385013d4fe6fdc4bcb35">Disabling TLS 1.1 in Spinnaker and Specifying the Protocols to be used&lt;/a> and &lt;a href="https://support.armory.io/support?sys_kb_id=e06335f11b202c1013d4fe6fdc4bcbf8&amp;amp;id=kb_article_view&amp;amp;sysparm_rank=1&amp;amp;sysparm_tsqueryId=3b0341771b3d385013d4fe6fdc4bcb6a">How to fix TLS error &amp;ldquo;Reason: extension (5) should not be presented in certificate_request&amp;rdquo;&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="deployment">Deployment&lt;/h2>
&lt;p>You have two options for deploying Clouddriver with MySQL: a simpler deployment, which involves downtime, or a three-step method that avoids downtime. Pick the method that best fits your requirements.&lt;/p>
&lt;h3 id="simple-deployment">Simple deployment&lt;/h3>
&lt;p>If you are not worried about downtime or if Spinnaker is not currently executing any pipelines, you can run a simple deployment by adding the following snippet to &lt;code>SpinnakerService&lt;/code> manifest under &lt;code>spec.spinnakerConfig.profiles.clouddriver&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">taskRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># These parameters were determined to be optimal via benchmark comparisons&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># in the Netflix production environment with Aurora. Setting these too low&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># or high may negatively impact performance. These values may be sub-optimal&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># in some environments.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">readBatchSize&lt;/span>: &lt;span style="color:#bd93f9">500&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">writeBatchSize&lt;/span>: &lt;span style="color:#bd93f9">300&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scheduler&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">connectionPools&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># additional connection pool parameters are available here,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># for more detail and to view defaults, see:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># https://github.com/spinnaker/kork/blob/master/kork-sql/src/main/kotlin/com/netflix/spinnaker/kork/sql/config/ConnectionPoolProperties.kt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># password: depending on db auth and how spinnaker secrets are managed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># The following tasks connection pool is optional. At Netflix, clouddriver&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># instances pointed to Aurora read replicas have a tasks pool pointed at the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># master. Instances where the default pool is pointed to the master omit a&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># separate tasks pool.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">migration&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_migrate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scheduler&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">taskRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="no-downtime-deployment">No downtime deployment&lt;/h3>
&lt;p>To avoid downtime for your deployment, use the following three steps:&lt;/p>
&lt;h4 id="step-1--warm-up-the-cache">Step 1: Warm up the cache&lt;/h4>
&lt;p>The first step is to start a Clouddriver that is not accessible from other services to validate the installation and warm up the cache.&lt;/p>
&lt;p>You can do it manually or by using the &lt;a href="https://gist.github.com/ncknt/983bb800451f00b39401852fefde69bf">following script&lt;/a>. Make sure tables are properly created and being populated by these instances of Clouddriver.&lt;/p>
&lt;h4 id="step-2--use-mysql-to-back-new-tasks">Step 2: Use MySQL to back new tasks&lt;/h4>
&lt;p>After waiting a few minutes (from 2 to 10 minutes depending on how many accounts are connected), we&amp;rsquo;ll update Spinnaker to use MySQL but remain aware of task statuses in Redis.&lt;/p>
&lt;p>We&amp;rsquo;re deploying Spinnaker with the following configuration in &lt;code>SpinnakerService&lt;/code> manifest under the key &lt;code>spec.spinnakerConfig.profiles.clouddriver&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">taskRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># These parameters were determined to be optimal via benchmark comparisons&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># in the Netflix production environment with Aurora. Setting these too low&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># or high may negatively impact performance. These values may be sub-optimal&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># in some environments.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">readBatchSize&lt;/span>: &lt;span style="color:#bd93f9">500&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">writeBatchSize&lt;/span>: &lt;span style="color:#bd93f9">300&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scheduler&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">connectionPools&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># additional connection pool parameters are available here,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># for more detail and to view defaults, see:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># https://github.com/spinnaker/kork/blob/master/kork-sql/src/main/kotlin/com/netflix/spinnaker/kork/sql/config/ConnectionPoolProperties.kt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># password: depending on db auth and how spinnaker secrets are managed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># The following tasks connection pool is optional. At Netflix, clouddriver&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># instances pointed to Aurora read replicas have a tasks pool pointed at the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># master. Instances where the default pool is pointed to the master omit a&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># separate tasks pool.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">migration&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_migrate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scheduler&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">executionRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dual&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">primaryName&lt;/span>: sqlExecutionRepository
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">previousClass&lt;/span>: redisExecutionRepository
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>At this point, you can stop the pods you created in step 1. If you used the preceding script, just delete the &lt;code>spin-clouddriver-sql&lt;/code> deployment.&lt;/p>
&lt;/blockquote>
&lt;h4 id="step-3--remove-redis">Step 3: Remove Redis&lt;/h4>
&lt;p>After waiting a few minutes so that Redis tasks are no longer relevant, finish by removing Redis entirely:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">taskRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># These parameters were determined to be optimal via benchmark comparisons&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># in the Netflix production environment with Aurora. Setting these too low&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># or high may negatively impact performance. These values may be sub-optimal&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># in some environments.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">readBatchSize&lt;/span>: &lt;span style="color:#bd93f9">500&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">writeBatchSize&lt;/span>: &lt;span style="color:#bd93f9">300&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scheduler&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">connectionPools&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># additional connection pool parameters are available here,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># for more detail and to view defaults, see:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># https://github.com/spinnaker/kork/blob/master/kork-sql/src/main/kotlin/com/netflix/spinnaker/kork/sql/config/ConnectionPoolProperties.kt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># password: depending on db auth and how spinnaker secrets are managed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># The following tasks connection pool is optional. At Netflix, clouddriver&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># instances pointed to Aurora read replicas have a tasks pool pointed at the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># master. Instances where the default pool is pointed to the master omit a&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># separate tasks pool.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">migration&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: clouddriver_migrate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://your.database:3306/clouddriver
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scheduler&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">taskRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Continuous-Deployment: Configure Dynamic Kubernetes Accounts</title><link>/continuous-deployment/armory-admin/dynamic-accounts-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/dynamic-accounts-configure/</guid><description>
&lt;h2 id="overview-of-external-account-configuration">Overview of external account configuration&lt;/h2>
&lt;p>If you add, delete, or modify Kubernetes deployment targets on a regular basis, you may find that redeploying Clouddriver to pull in new
account configuration impacts your teams. Spinnaker&amp;rsquo;s &lt;a href="https://www.spinnaker.io/setup/configuration/#external-account-configuration">External Account Configuration&lt;/a> feature allows you to manage account configuration
externally from Spinnaker and then read that configuration change without requiring a redeployment of Clouddriver.&lt;/p>
&lt;blockquote>
&lt;p>External Account Configuration is only supported for Kubernetes and Cloud Foundry provider accounts. This document describes how this works with Kubernetes accounts.&lt;/p>
&lt;/blockquote>
&lt;p>Armory does not recommend using External Account Configuration with Spring Cloud Config Server. If you have an existing environment with Spring Cloud Config Server with this setup, see the following KB article: &lt;a href="https://support.armory.io/support?id=kb_article_view&amp;amp;sysparm_article=KB0010418">Configure Spinnaker&amp;rsquo;s External Account Configuration with Vault&lt;/a>.&lt;/p></description></item><item><title>Continuous-Deployment: Configure Gate and Deck to Run on the Same Hostname</title><link>/continuous-deployment/armory-admin/hostname-deck-gate-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/hostname-deck-gate-configure/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>The Spinnaker&lt;sup>TM&lt;/sup> microservice Gate serves as the API gateway for
Armory and is leveraged by the Deck microservice to display various Armory data
via a user interface. In order to successfully use the Deck UI, both Deck and
Gate must be accessible via DNS. The standard approach to configuring access to
both Deck and Gate is to set DNS routing to each service on separate hostnames
or separate sub-domains of the same hostname. While this approach is typical,
it increases the complexity of both DNS management and Ingress management into
Kubernetes.&lt;/p>
&lt;p>To simplify both DNS management and Ingress management, Armory can be configured
to serve the Gate microservice on the same hostname as the Deck UI but located
at a sub-path. We recommend configuring the Gate microservice so that it is served from the &lt;code>/api/v1&lt;/code> of the Deck UI hostname when using a single hostname for both Deck and Gate.&lt;/p>
&lt;h2 id="prerequisites-for-running-on-the-same-host">Prerequisites for running on the same host&lt;/h2>
&lt;ul>
&lt;li>Deck is accessible at &lt;code>https://spinnaker.example.com&lt;/code>&lt;/li>
&lt;li>Gate is accessible at &lt;code>https://spinnaker.example.com/api/v1&lt;/code>&lt;/li>
&lt;li>Kubernetes Ingress and Service is used to route traffic from these paths to port 8084 on Gate and 9000 on Deck.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Note: Configuring a Kubernetes Ingress and Service is outside the scope of this document.&lt;/p>
&lt;/blockquote>
&lt;h2 id="configure-spinnaker">Configure Spinnaker&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>Set Gate&amp;rsquo;s server servlet to be aware of its context path at &lt;code>/api/v1&lt;/code> in your &lt;code>SpinnakerService&lt;/code> config.&lt;/p>
&lt;p>Add the following under the &lt;code>spec.spinnakerConfig.profiles&lt;/code> section:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">gate&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">servlet&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">context-path&lt;/span>: /api/v1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Set Gate&amp;rsquo;s health endpoint to &lt;code>/api/v1/health&lt;/code> in your &lt;code>SpinnakerService&lt;/code> config.&lt;/p>
&lt;p>Add the following under the &lt;code>spec.spinnakerConfig.service-settings&lt;/code> section:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">gate&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">healthEndpoint&lt;/span>: /api/v1/health
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Update Deck&amp;rsquo;s URL in your &lt;code>SpinnakerService&lt;/code> config.&lt;/p>
&lt;p>Add the following under the &lt;code>spec.config.security&lt;/code> section:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">uiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">overrideBaseUrl&lt;/span>: https://spinnaker.example.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Update Gate&amp;rsquo;s URL in your &lt;code>SpinnakerService&lt;/code> config.&lt;/p>
&lt;p>Add the following under the &lt;code>spec.config.security&lt;/code> section:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">overrideBaseUrl&lt;/span>: https://spinnaker.example.com/api/v1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Deploy your &lt;code>SpinnakerService&lt;/code> config using either &lt;code>kubectl&lt;/code> or &lt;code>kustomize&lt;/code> command syntax&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>Continuous-Deployment: Configure GitHub OAuth for Spinnaker</title><link>/continuous-deployment/armory-admin/authn-github/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/authn-github/</guid><description>
&lt;h2 id="before-you-begin">Before you begin&lt;/h2>
&lt;ul>
&lt;li>You have the ability to modify developer settings for your GitHub organization.&lt;/li>
&lt;li>You have a Spinnaker&lt;sup>TM&lt;/sup> instance with &lt;a href="/continuous-deployment/armory-admin/dns-and-ssl/">DNS and SSL&lt;/a> configured.&lt;/li>
&lt;/ul>
&lt;h2 id="configure-github-oauth-in-github">Configure GitHub OAuth in GitHub&lt;/h2>
&lt;p>Follow the instructions in GitHub&amp;rsquo;s &lt;a href="https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app">Creating an OAuth App&lt;/a> guide.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Homepage URL&lt;/strong>: This is the URL of your the Gate service; for example, &lt;code>https://gate.spinnaker.acme.com&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Authorization callback URL&lt;/strong>: The URL needs &lt;code>login&lt;/code> appended to your Gate endpoint; for example, &lt;code>https://gate.spinnaker.acme.com/login&lt;/code> or &lt;code>https://spinnaker.acme.com/gate/login&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h2 id="configure-github-oauth-in-spinnaker">Configure GitHub OAuth in Spinnaker&lt;/h2>
&lt;p>Add the following snippet to your &lt;code>SpinnakerService&lt;/code> manifest under the &lt;code>spec.spinnakerConfig.config.security.authn&lt;/code> level:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">client&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientId&lt;/span>: a08xxxxxxxxxxxxx93
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientSecret&lt;/span>: 6xxxaxxxxxxxxxxxxxxxxxxx59 &lt;span style="color:#6272a4"># Secret Enabled Field&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">scope&lt;/span>: read:org,user:email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">provider&lt;/span>: GITHUB
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Review the &lt;a href="/continuous-deployment/installation/armory-operator/op-manifest-reference/"}>Armory Continuous Deployment Manifest Configuration Reference&lt;/a> for additional configuration options.&lt;/p>
&lt;h2 id="whats-next">What&amp;rsquo;s next&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://www.spinnaker.io/setup/security/authentication/oauth/">Spinnaker: OAuth&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://help.github.com/en/articles/authorizing-oauth-apps">Github: OAuth&lt;/a>&lt;/li>
&lt;li>&lt;a href="/continuous-deployment/armory-admin/dns-and-ssl/">Armory: DNS and SSL&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.spinnaker.io/setup/security/ssl/">Spinnaker: SSL&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Continuous-Deployment: Configure mTLS for Spinnaker Services</title><link>/continuous-deployment/armory-admin/mtls-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/mtls-configure/</guid><description>
&lt;h2 id="overview-of-mtls">Overview of mTLS&lt;/h2>
&lt;p>mTLS is a transport level security measure. When a client connects to a server, as in a TLS connection:&lt;/p>
&lt;ul>
&lt;li>The server responds with its certificate. Additionally, the server sends a certificate request and a list of Distinguished Names the server recognizes.&lt;/li>
&lt;li>The client verifies the certificate of the server and responds with its own certificate and the Distinguished Name its certificate was (in)directly signed with.&lt;/li>
&lt;li>The server verifies the certificate of the client.&lt;/li>
&lt;/ul>
&lt;p>To set up TLS, provide the following:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>For a server:&lt;/p>
&lt;ul>
&lt;li>Certificate and private key&lt;/li>
&lt;li>Chain of certificates to validate clients&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>For a client:&lt;/p>
&lt;ul>
&lt;li>Certificate and private key to present to the server&lt;/li>
&lt;li>Chain of certificates to validate the server (if self signed)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>For information about TLS, see &lt;a href="/continuous-deployment/armory-admin/tls-configure/"}>Configure TLS for Spinnaker Services&lt;/a>.&lt;/p>
&lt;h2 id="what-you-need">What you need&lt;/h2>
&lt;p>The following table lists the Armory and Spinnaker services, their type (Java or Golang), and which certificates they need:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Service&lt;/th>
&lt;th>Type&lt;/th>
&lt;th>Server&lt;/th>
&lt;th>Client&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Clouddriver&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Deck&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>-&lt;/td>
&lt;td>-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Dinghy*&lt;/td>
&lt;td>Golang&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Echo&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Fiat&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Front50&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Gate&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Maybe&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Kayenta&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Igor&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Orca&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Rosco&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Terraformer*&lt;/td>
&lt;td>Golang&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>Dinghy is the service for Pipelines-as-Code.&lt;/li>
&lt;li>Terraformer is the service for the Armory Terraform Integration.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Note&lt;/strong>: Gate may be handled differently if you already &lt;a href="/continuous-deployment/armory-admin/dns-and-ssl/">terminating SSL at Gate&lt;/a>. If not, make sure the load balancer and ingress you are using supports self-signed certificates.&lt;/p>
&lt;p>In the following sections, you need to have the following information available:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ca.pem&lt;/code> (all Golang servers): the CA certificate in PEM format&lt;/li>
&lt;li>&lt;code>[service].crt&lt;/code> (each Golang server): the certificate and (optionally) the private key of the Golang server in PEM format&lt;/li>
&lt;li>&lt;code>[service].key&lt;/code> (each Golang server): the private key of the Golang server if not bundled with the certificate you&amp;rsquo;re using&lt;/li>
&lt;li>&lt;code>[GOSERVICE]_KEY_PASS&lt;/code> (each Golang server): the password to the private key of the server&lt;/li>
&lt;li>&lt;code>truststore.p12&lt;/code> (all Java clients): a PKCS12 truststore with CA certificate imported&lt;/li>
&lt;li>&lt;code>TRUSTSTORE_PASS&lt;/code> (all Java clients): the password to the truststore you&amp;rsquo;re using&lt;/li>
&lt;li>&lt;code>[service].p12&lt;/code> (each Java server): a PKCS12 keystore containing the certificate and private key of the server&lt;/li>
&lt;li>&lt;code>[SERVICE]_KEY_PASS&lt;/code> (each Java server): the password to the keystore you&amp;rsquo;re using&lt;/li>
&lt;/ul>
&lt;p>The server certificate will serve as its client certificate to other services. You can generate different certificates and use them in &lt;code>ok-http-client.key-store*&lt;/code> (Java) and &lt;code>http.key*&lt;/code> (Golang).&lt;/p>
&lt;p>To learn how to generate these files, see the &lt;a href="/continuous-deployment/armory-admin/generating-certificates/"}>Generate Certificates for Spinnaker&lt;/a> guide.&lt;/p>
&lt;h2 id="configuring-java-services">Configuring Java services&lt;/h2>
&lt;p>Add the following to each Java service under &lt;code>profiles&lt;/code> in the &lt;a href="/continuous-deployment/installation/armory-operator/op-config-manifest/#specspinnakerconfigprofiles">SpinnakerService&amp;rsquo;s profiles&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Only needed for &amp;#34;server&amp;#34; role&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: &amp;lt;reference to [service].p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-password&lt;/span>: &amp;lt;[SERVICE]_KEY_PASS&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store&lt;/span>: &amp;lt;reference to ca.p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-password&lt;/span>: &amp;lt;TRUSTSTORE_PASS&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Roll out with &amp;#34;want&amp;#34; initially&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">client-auth&lt;/span>: need
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Needed for all Java services&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">ok-http-client&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: &amp;lt;reference to [service].p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-password&lt;/span>: [SERVICE]_KEY_PASS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store&lt;/span>: &amp;lt;reference to truststore.p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-password&lt;/span>: &amp;lt;TRUSTSTORE_PASS&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="configuring-golang-services">Configuring Golang services&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">certFile&lt;/span>: &amp;lt;reference to [service].crt&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyFile&lt;/span>: &amp;lt;reference to [service].key if not included in the certFile&amp;#39;s PEM&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyPassword&lt;/span>: &amp;lt;[GOSERVICE]_KEY_PASS if required&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cacertFile&lt;/span>: &amp;lt;reference to ca.pem&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Roll out with &amp;#34;want&amp;#34; initially&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientAuth&lt;/span>: need
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">http&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cacertFile&lt;/span>: &amp;lt;reference to ca.pem&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientCertFile&lt;/span>: &amp;lt;reference to [service].crt&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientKeyFile&lt;/span>: &amp;lt;reference to [service.key]&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientKeyPassword&lt;/span>: &amp;lt;[GOSERVICE]_KEY_PASS if required&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="changing-service-endpoints">Changing service endpoints&lt;/h2>
&lt;p>Use the Operator to change Spinnaker&amp;rsquo;s service endpoints.&lt;/p>
&lt;p>Change the SpinnakerService custom resource:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">service-settings&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clouddriver&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-clouddriver.&amp;lt;NAMESPACE&amp;gt;:7002
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dinghy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-dinghy.&amp;lt;NAMESPACE&amp;gt;:8081
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">echo&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-echo.&amp;lt;NAMESPACE&amp;gt;:8089
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">fiat&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-fiat.&amp;lt;NAMESPACE&amp;gt;:7003
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">front50&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-front50.&amp;lt;NAMESPACE&amp;gt;:8080
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">gate&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-gate.&amp;lt;NAMESPACE&amp;gt;:8084
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kayenta&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-kayenta.&amp;lt;NAMESPACE&amp;gt;:8090
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">orca&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-orca.&amp;lt;NAMESPACE&amp;gt;:8083
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">igor&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-igor.&amp;lt;NAMESPACE&amp;gt;:8088
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rosco&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-rosco.&amp;lt;NAMESPACE&amp;gt;:8087
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">terraformer&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-terraformer.&amp;lt;NAMESPACE&amp;gt;:7088
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;h2 id="changing-readiness-probe">Changing readiness probe&lt;/h2>
&lt;p>Change the readiness probe used by Kubernetes from an HTTP request to a TCP probe.&lt;/p>
&lt;p>Add the following snippet to each service in &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">service-settings&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">&amp;lt;service&amp;gt;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kubernetes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">useTcpProbe&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="deployment">Deployment&lt;/h2>
&lt;p>Apply your changes to your Spinnaker deployment:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If Spinnaker services are already using HTTPS, you can roll out mTLS without interruption by making the client certificate optional (&lt;code>want&lt;/code>) in &lt;code>server.ssl.client-auth&lt;/code> (Java) and &lt;code>server.ssl.clientAuth&lt;/code>. Then once all the services are stable, rolling out a new configuration with that value set to &lt;code>need&lt;/code>.&lt;/p></description></item><item><title>Continuous-Deployment: Configure Auth for Spinnaker Using Okta SAML</title><link>/continuous-deployment/armory-admin/auth-okta-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/auth-okta-configure/</guid><description>
&lt;h2 id="configure-a-spinnaker-application-in-okta">Configure a Spinnaker application in Okta&lt;/h2>
&lt;p>Select &lt;strong>Applications&lt;/strong> &amp;gt; &lt;strong>Applications&lt;/strong> from the top menu.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-applications.png"/>
&lt;/figure>
&lt;/p>
&lt;p>Click the &lt;strong>Add Application&lt;/strong> button.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-addapplication.png"/>
&lt;/figure>
&lt;/p>
&lt;p>Click the &lt;strong>Create New App&lt;/strong> button.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-createnewapp.png"/>
&lt;/figure>
&lt;/p>
&lt;p>In the dialog &lt;strong>Create a New Application Integration&lt;/strong>, select the following values:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Platform&lt;/strong> &amp;gt; Web&lt;/li>
&lt;li>&lt;strong>Sign on method&lt;/strong> &amp;gt; SAML 2.0&lt;/li>
&lt;/ul>
&lt;p>Then click the &lt;strong>Create&lt;/strong> button.&lt;/p>
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-createnewintegration.png"/>
&lt;/figure>
&lt;p>On the &lt;strong>Create SAML Integration&lt;/strong> screen, enter an app name and click the &lt;strong>Next&lt;/strong> button.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-appname.png"/>
&lt;/figure>
&lt;/p>
&lt;p>On the &lt;strong>Configure SAML&lt;/strong> screen, configure the following settings:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Single sign on URL&lt;/strong>: Enter the URL for your Gate service, with the path &lt;code>/saml/SSO&lt;/code>. For example, &lt;code>https://oktaspinnaker.spinnaker.armory.io:8084/saml/SSO&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Audience URI (SP Entity ID)&lt;/strong>: Enter a unique entity id. For example, &lt;code>io.armory.spinnaker.oktatest&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Name ID format&lt;/strong>: For example, &amp;ldquo;EmailAddress&amp;rdquo;&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Application username&lt;/strong>: For example, &amp;ldquo;Email&amp;rdquo;&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>In the &lt;strong>GROUP ATTRIBUTE STATEMENTS&lt;/strong> section:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Name&lt;/strong> = memberOf, &lt;strong>Name format&lt;/strong> = Unspecified, &lt;strong>Filter&lt;/strong> = Regex: .*&lt;/li>
&lt;/ul>
&lt;p>Then, click the &lt;strong>Next&lt;/strong> button.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-samlsettings.png"/>
&lt;/figure>
&lt;/p>
&lt;p>On the &lt;strong>Create SAML Integration&lt;/strong> screen, select &lt;strong>I&amp;rsquo;m an Okta customer adding an internal app&lt;/strong> and then click the &lt;strong>Finish&lt;/strong> button.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-feedback.png"/>
&lt;/figure>
&lt;/p>
&lt;p>This takes you to the &lt;strong>Sign On&lt;/strong> screen of the application you just created.&lt;/p>
&lt;p>Click the &lt;strong>View Setup Instructions&lt;/strong> button. This displays the page with information necessary to configure Spinnaker.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-viewsetupinstructions.png"/>
&lt;/figure>
&lt;/p>
&lt;p>In the &lt;strong>Optional&lt;/strong> section, copy the contents of IDP metadata and save to file. For example, under &lt;code>/Users/armory/.hal/saml/metadata.xml&lt;/code>.
&lt;figure>
&lt;img src="/images/armory-admin/artifacts/okta/okta-idpmetadata.png"/>
&lt;/figure>
&lt;/p>
&lt;h2 id="configure-spinnaker-to-use-okta">Configure Spinnaker to use Okta&lt;/h2>
&lt;h3 id="1-create-a-saml-keystore-file">1: Create a SAML keystore file&lt;/h3>
&lt;blockquote>
&lt;p>Make sure the Java version used to generate the keystore is the same version used to run Armory Continuous Deployment or Spinnaker.&lt;/p>
&lt;/blockquote>
&lt;p>Generate a keystore and key:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">KEYSTORE_PATH&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>/Users/armory/.hal/saml/saml.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keytool -genkey -v -keystore KEYSTORE_PATH -alias saml -keyalg RSA -keysize &lt;span style="color:#bd93f9">2048&lt;/span> -validity &lt;span style="color:#bd93f9">10000&lt;/span> -storetype JKS
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="2-configure-spinnaker-to-use-saml">2: Configure Spinnaker to use SAML&lt;/h3>
&lt;blockquote>
&lt;p>The value you enter for &lt;code>issuerId&lt;/code> must match the value entered in &lt;strong>Audience URI (SP Entity ID)&lt;/strong> when configuring the app in Okta&lt;/p>
&lt;/blockquote>
&lt;p>Add the following snippet to &lt;code>SpinnakerService&lt;/code> manifest. This references secrets stored in a Kubernetes secrets in the same namespace as Spinnaker, but secrets can be stored in any of the supported &lt;a href="/continuous-deployment/armory-admin/secrets/">secret engines&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">authn&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">saml&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyStore&lt;/span>: encryptedFile:k8s!n:spin-secrets!k:saml.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyStoreAliasName&lt;/span>: saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyStorePassword&lt;/span>: encrypted:k8s!n:spin-secrets!k:keystorePassword
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">metadataLocal&lt;/span>: encryptedFile:k8s!n:spin-secrets!k:metadata.xml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">issuerId&lt;/span>: io.armory.spinnaker.oktatest &lt;span style="color:#6272a4"># The identity of the Spinnaker application registered with the SAML provider.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">serviceAddress&lt;/span>: https://&amp;lt;gate-URL&amp;gt; &lt;span style="color:#6272a4"># The address of the Gate server that will be accesible by the SAML identity provider. This should be the full URL, including port, e.g. https://gate.org.com:8084/. If deployed behind a load balancer, this would be the laod balancer&amp;#39;s address.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create the Kubernetes secret holding the Spinnaker secrets:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; create secret generic spin-secrets &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --from-file&lt;span style="color:#ff79c6">=&lt;/span>saml.jks &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --from-file&lt;span style="color:#ff79c6">=&lt;/span>metadata.xml &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --from-literal&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">keystorePassword&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&amp;lt;password-entered-in-step-1&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Apply your changes to the &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>
&lt;p>Make sure the DNS is correctly pointing to the load balancers of &lt;code>gate-URL&lt;/code> and &lt;code>deck-URL&lt;/code>.&lt;/p>
&lt;p>Verify that the &lt;code>gate-URL&lt;/code> is the one entered in Okta with &lt;code>:8084/saml/SSO&lt;/code> appended to it.&lt;/p>
&lt;p>Validate that the &lt;code>service-address-url&lt;/code> in your configuration is the &lt;code>gate-URL&lt;/code>.&lt;/p></description></item><item><title>Continuous-Deployment: Configure Spinnaker's Orca Service to Use SQL RDBMS</title><link>/continuous-deployment/armory-admin/orca-sql-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/orca-sql-configure/</guid><description>
&lt;h2 id="advantages-to-using-an-rdms-with-orca">Advantages to using an RDMS with Orca&lt;/h2>
&lt;p>By default, Spinnaker&amp;rsquo;s task orchestration service, Orca, uses Redis as its backing store. You can configure Orca to use a relational database instead of Redis to store its pipeline execution. The main advantage of doing so is a gain in performance and the removal of Redis as a single point of failure.&lt;/p>
&lt;p>Armory recommends MySQL 5.7. For AWS, you can use Aurora.&lt;/p>
&lt;h2 id="base-configuration">Base configuration&lt;/h2>
&lt;p>You can find a complete description of configuration options in the Open Source Spinnaker &lt;a href="https://www.spinnaker.io/setup/productionize/persistence/orca-sql/">documentation&lt;/a>.&lt;/p>
&lt;p>You can configure your SQL database by adding the following snippet to &lt;code>SpinnakerService&lt;/code> manifest under &lt;code>spec.spinnakerConfig.profiles.orca&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">connectionPools&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://&amp;lt;DB CONNECTION HOSTNAME&amp;gt;:&amp;lt;DB CONNECTION PORT&amp;gt;/&amp;lt;DATABASE NAME&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: orca_service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">password&lt;/span>: &amp;lt;orca_service password&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">connectionTimeoutMs&lt;/span>: &lt;span style="color:#bd93f9">5000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">maxLifetimeMs&lt;/span>: &lt;span style="color:#bd93f9">30000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">maxPoolSize&lt;/span>: &lt;span style="color:#bd93f9">50&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">migration&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jdbcUrl&lt;/span>: jdbc:mysql://&amp;lt;DB CONNECTION HOSTNAME&amp;gt;:&amp;lt;DB CONNECTION PORT&amp;gt;/&amp;lt;DATABASE NAME&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">user&lt;/span>: orca_migrate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">password&lt;/span>: &amp;lt;orca_migrate password&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Ensure we&amp;#39;re only using SQL for accessing execution state&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">executionRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">monitor&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">activeExecutions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">redis&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Depending on your TLS settings, you may need to configure TLS 1.2. For more information, see the Knowledge Base articles &lt;a href="https://support.armory.io/support?sys_kb_id=6d38e4bfdba47c1079f53ec8f49619c2&amp;amp;id=kb_article_view&amp;amp;sysparm_rank=2&amp;amp;sysparm_tsqueryId=f93349771b3d385013d4fe6fdc4bcb35">Disabling TLS 1.1 in Spinnaker and Specifying the Protocols to be used&lt;/a> and &lt;a href="https://support.armory.io/support?sys_kb_id=e06335f11b202c1013d4fe6fdc4bcbf8&amp;amp;id=kb_article_view&amp;amp;sysparm_rank=1&amp;amp;sysparm_tsqueryId=3b0341771b3d385013d4fe6fdc4bcb6a">How to fix TLS error &amp;ldquo;Reason: extension (5) should not be presented in certificate_request&amp;rdquo;&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="create-the-orca-database-and-configure-authorization">Create the &lt;code>orca&lt;/code> database and configure authorization&lt;/h2>
&lt;p>Once you&amp;rsquo;ve provisioned your RDBMS and ensured connectivity from Spinnaker, you need to create the database. You can skip this step if you created the database during provisioning.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">CREATE&lt;/span> &lt;span style="color:#ff79c6">SCHEMA&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>orca&lt;span style="color:#ff79c6">`&lt;/span> &lt;span style="color:#ff79c6">DEFAULT&lt;/span> &lt;span style="color:#8be9fd;font-style:italic">CHARACTER&lt;/span> &lt;span style="color:#ff79c6">SET&lt;/span> utf8mb4 &lt;span style="color:#ff79c6">COLLATE&lt;/span> utf8mb4_unicode_ci;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Grant authorization to the &lt;code>orca_service&lt;/code> and &lt;code>orca_migrate&lt;/code> users:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">GRANT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">SELECT&lt;/span>, &lt;span style="color:#ff79c6">INSERT&lt;/span>, &lt;span style="color:#ff79c6">UPDATE&lt;/span>, &lt;span style="color:#ff79c6">DELETE&lt;/span>, &lt;span style="color:#ff79c6">EXECUTE&lt;/span>, &lt;span style="color:#ff79c6">SHOW&lt;/span> &lt;span style="color:#ff79c6">VIEW&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ON&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>orca&lt;span style="color:#ff79c6">`&lt;/span>.&lt;span style="color:#ff79c6">*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">TO&lt;/span> &lt;span style="color:#f1fa8c">&amp;#39;orca_service&amp;#39;&lt;/span>&lt;span style="color:#ff79c6">@&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;%&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">GRANT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">SELECT&lt;/span>, &lt;span style="color:#ff79c6">INSERT&lt;/span>, &lt;span style="color:#ff79c6">UPDATE&lt;/span>, &lt;span style="color:#ff79c6">DELETE&lt;/span>, &lt;span style="color:#ff79c6">CREATE&lt;/span>, &lt;span style="color:#ff79c6">DROP&lt;/span>, &lt;span style="color:#ff79c6">REFERENCES&lt;/span>, &lt;span style="color:#ff79c6">INDEX&lt;/span>, &lt;span style="color:#ff79c6">ALTER&lt;/span>, &lt;span style="color:#ff79c6">LOCK&lt;/span> TABLES, &lt;span style="color:#ff79c6">EXECUTE&lt;/span>, &lt;span style="color:#ff79c6">SHOW&lt;/span> &lt;span style="color:#ff79c6">VIEW&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ON&lt;/span> &lt;span style="color:#ff79c6">`&lt;/span>orca&lt;span style="color:#ff79c6">`&lt;/span>.&lt;span style="color:#ff79c6">*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">TO&lt;/span> &lt;span style="color:#f1fa8c">&amp;#39;orca_migrate&amp;#39;&lt;/span>&lt;span style="color:#ff79c6">@&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;%&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above configuration grants authorization from any host. You can restrict it to the cluster in which Spinnaker runs by replacing the &lt;code>%&lt;/code> with the IP address of Orca pods from MySQL.&lt;/p>
&lt;h2 id="migrate-from-redis-to-sql-to-keep-existing-execution-history">Migrate from Redis to SQL to keep existing execution history&lt;/h2>
&lt;p>The above configuration will point Orca to your database.
You have the option to run a dual repository by adding &lt;code>dual&lt;/code> in &lt;code>profiles/orca-local.yml&lt;/code>.&lt;/p>
&lt;p>Armory v2.18+:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">executionRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dual&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">primaryName&lt;/span>: sqlExecutionRepository
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">previousName&lt;/span>: redisExecutionRepository
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Armory versions prior to v2.18:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">executionRepository&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dual&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">primaryClass&lt;/span>: com.netflix.spinnaker.orca.sql.pipeline.persistence.SqlExecutionRepository
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">previousClass&lt;/span>: com.netflix.spinnaker.orca.pipeline.persistence.jedis.RedisExecutionRepository
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sql&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">redis&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>However, this configuration won&amp;rsquo;t migrate your existing execution history to your new database. This will make your Spinnaker instance run on both the SQL and Redis backend. Spinnaker will only write the new execution on SQL but will continue to read the data on Redis.
To migrate the data from Redis to SQL, you need to add the following&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">pollers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">orchestrationMigrator&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">intervalMs&lt;/span>: &lt;span style="color:#bd93f9">1800000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">pipelineMigrator&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">intervalMs&lt;/span>: &lt;span style="color:#bd93f9">1800000&lt;/span> &lt;span style="color:#6272a4"># After how much time the migration process is going to start&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once everything has been migrated (you will see logs in the orca pod about the migration process) you can remove these settings.&lt;/p>
&lt;!-- ## Support for Other Relational Databases
&lt;div class="alpha-warning">
Database engines other than MySQL and its variants such as Aurora with MySQL are not currently officially supported.
&lt;/div>
To try a different database you can switch the JDBC URL and set the `dialect` in the properties:
```yaml
sql:
enabled: true
connectionPools:
jdbcUrl: jdbc:&lt;DRIVER>://&lt;DB CONNECTION HOSTNAME>:&lt;DB CONNECTION PORT>/&lt;DATABASE NAME>
dialect: &lt;DIALECT VALUE>
...
migration:
jdbcUrl: jdbc:&lt;DRIVER>://&lt;DB CONNECTION HOSTNAME>:&lt;DB CONNECTION PORT>/&lt;DATABASE NAME>
dialect: &lt;DIALECT VALUE>
...
```
You can find the dialect below:
| Database | Dialect Value |
| ------------ | --------------- |
| MariaDB | `MARIADB` |
| MySQL | `MYSQL` (default) |
| PostgreSQL | `POSTGRES` |
| PostgreSQL 9.3 | `POSTGRES_9_3` |
| PostgreSQL 9.4 | `POSTGRES_9_4` |
| PostgreSQL 9.5 | `POSTGRES_9_5` | -->
&lt;h2 id="database-maintenance">Database maintenance&lt;/h2>
&lt;p>Each new version of Orca may potentially migrate the database schema. This is done with the &lt;code>orca_migrate&lt;/code> user defined above.&lt;/p>
&lt;p>Pipeline executions are saved to the database. Each execution can add between a few KBs to hundreds of KBs of data depending on the size of your pipeline.
It means that after a while, data will grow large and you&amp;rsquo;ll likely want to purge older executions.&lt;/p>
&lt;p>Note: We recommend saving past executions to a different data store for auditing purposes. You can do it in a variety of ways:&lt;/p>
&lt;ul>
&lt;li>During the purge, by marking, exporting, then deleting older records.&lt;/li>
&lt;li>By saving execution history from Echo&amp;rsquo;s events and just delete older records from your database.&lt;/li>
&lt;/ul></description></item><item><title>Continuous-Deployment: Configure Slack Notifications in Spinnaker</title><link>/continuous-deployment/armory-admin/notifications-slack-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/notifications-slack-configure/</guid><description>
&lt;h2 id="create-a-slack-application">Create a Slack application&lt;/h2>
&lt;p>Go to the &lt;a href="https://api.slack.com/apps">Apps Management URL&lt;/a> and click on the “Create New App” button. Once done, you get access to the basic configuration pane. You might want to customize some settings, like the color or the logo of your application at the bottom of it.&lt;/p>
&lt;figure>
&lt;img src="/images/slack-notifications-1.png"/>
&lt;/figure>
&lt;h2 id="create-a-bot">Create a bot&lt;/h2>
&lt;p>Create a bot after your Slack application has been created. Next, select the “Add features and functionality” menu and then select “Bots”.&lt;/p>
&lt;p>Enter the following fields:&lt;/p>
&lt;ul>
&lt;li>The Bot Display Name&lt;/li>
&lt;li>The Bot Username&lt;/li>
&lt;li>The “Always Show My Bot as Online” to On&lt;/li>
&lt;/ul>
&lt;h2 id="deploy-the-bot">Deploy the bot&lt;/h2>
&lt;p>Select the “OAuth &amp;amp; Permissions” menu, copy the &lt;em>Bot User OAuth Access Token&lt;/em> this is the token needed in Spinnaker configuration, also on the &lt;em>Bot Token Scopes&lt;/em> section add a scope of type &lt;code>chat:write&lt;/code> like in the screenshot below:&lt;/p>
&lt;figure>
&lt;img src="/images/slack-bot-credentials.png"/>
&lt;/figure>
&lt;p>Select the “Install your app to your workspace” from the Bot “Basic Information” page and deploy it.&lt;/p>
&lt;h2 id="invite-the-bot-to-a-channel">Invite the bot to a channel&lt;/h2>
&lt;p>Spinnaker only requires publishing on a channel to interact with Slack. All you have to do is connect to a channel or create a new channel and name the bot you’ve just created. Slack proposes to invite the bot. Accept the invitation.&lt;/p>
&lt;h2 id="register-the-slack-token-with-spinnaker">Register the Slack token with Spinnaker&lt;/h2>
&lt;p>You are now ready to configure Spinnaker with the bot you’ve just registered.&lt;/p>
&lt;p>Add the following snippet to the &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">notifications&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">slack&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">botName&lt;/span>: spinnaker &lt;span style="color:#6272a4"># The name of your slack bot.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">token&lt;/span>: xoxb-xxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx &lt;span style="color:#6272a4"># Your slack bot token. This field supports &amp;#34;encrypted&amp;#34; secret references&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Apply the changes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="test-spinnaker">Test Spinnaker&lt;/h2>
&lt;p>You should then make sure Spinnaker can send the notifications as expected. You can configure a notification within a channel you have invited your bot in and test by running a test pipeline. See example below:&lt;/p>
&lt;figure>
&lt;img src="/images/slack-notifications-3.png"/>
&lt;/figure></description></item><item><title>Continuous-Deployment: Configure TLS for Spinnaker Services</title><link>/continuous-deployment/armory-admin/tls-configure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/tls-configure/</guid><description>
&lt;blockquote>
&lt;p>Switching from plain HTTP to HTTPS will cause some short disruption to the services as they become healthy at different times.&lt;/p>
&lt;/blockquote>
&lt;h2 id="overview-of-tls">Overview of TLS&lt;/h2>
&lt;p>When a client attempts to communicate with a server over SSL:&lt;/p>
&lt;ul>
&lt;li>the server must present a certificate to the user.&lt;/li>
&lt;li>the client must validate that certificate by checking it against its known valid certificate authorities (CA).&lt;/li>
&lt;/ul>
&lt;p>To properly set up TLS between services, we need to provide each service with:&lt;/p>
&lt;ol>
&lt;li>a certificate signed by a CA&lt;/li>
&lt;li>the CA certificate to verify these certificates&lt;/li>
&lt;/ol>
&lt;p>Note that distributing a CA public key is only needed if you sign certificates with a CA that is not bundled in most systems. &lt;strong>In this document, we assume that you are using a self-signed CA.&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Java&lt;/strong>&lt;/p>
&lt;p>Java services can present #1 as a keystore and #2 as a trust store in PKCS12 (preferred) or JKS format.&lt;/p>
&lt;p>&lt;strong>Golang&lt;/strong>&lt;/p>
&lt;p>Golang services need a X509 certificate (PEM format) and a private key for #1 as well as the X509 certificate of the CA for #2.&lt;/p>
&lt;h2 id="what-you-need">What you need&lt;/h2>
&lt;p>The following table lists the Armory and Spinnaker services, their type (Java or Golang), and which certificates they need:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Service&lt;/th>
&lt;th>Type&lt;/th>
&lt;th>Server&lt;/th>
&lt;th>Client&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Clouddriver&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Deck&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>-&lt;/td>
&lt;td>-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Dinghy*&lt;/td>
&lt;td>Golang&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Echo&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Fiat&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Front50&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Gate&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Maybe&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Kayenta&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Igor&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Orca&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Rosco&lt;/td>
&lt;td>Java&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Terraformer*&lt;/td>
&lt;td>Golang&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Yes&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>Dinghy is the service for Pipelines-as-Code.&lt;/li>
&lt;li>Terraformer is the service for the Armory Terraform Integration.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Note&lt;/strong>: Gate may be handled differently if you already &lt;a href="/continuous-deployment/armory-admin/dns-and-ssl/">terminating SSL at Gate&lt;/a>. If not, make sure the load balancer and ingress you are using supports self-signed certificates.&lt;/p>
&lt;p>In the following sections, you need to have the following information available:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ca.pem&lt;/code> (all Golang servers): the CA certificate in PEM format&lt;/li>
&lt;li>&lt;code>[service].crt&lt;/code> (each Golang server): the certificate and (optionally) the private key of the Golang server in PEM format&lt;/li>
&lt;li>&lt;code>[service].key&lt;/code> (each Golang server): the private key of the Golang server if not bundled with the certificate you&amp;rsquo;re using&lt;/li>
&lt;li>&lt;code>[GOSERVICE]_KEY_PASS&lt;/code> (each Golang server): the password to the private key of the server&lt;/li>
&lt;li>&lt;code>truststore.p12&lt;/code> (all Java clients): a PKCS12 truststore with CA certificate imported&lt;/li>
&lt;li>&lt;code>TRUSTSTORE_PASS&lt;/code> (all Java clients): the password to the truststore you&amp;rsquo;re using&lt;/li>
&lt;li>&lt;code>[service].p12&lt;/code> (each Java server): a PKCS12 keystore containing the certificate and private key of the server&lt;/li>
&lt;li>&lt;code>[SERVICE]_KEY_PASS&lt;/code> (each Java server): the password to the keystore you&amp;rsquo;re using&lt;/li>
&lt;/ul>
&lt;p>The server certificate will serve as its client certificate to other services. You can generate different certificates and use them in &lt;code>ok-http-client.key-store*&lt;/code> (Java) and &lt;code>http.key*&lt;/code> (Golang).&lt;/p>
&lt;p>To learn how to generate these files, see the &lt;a href="/continuous-deployment/armory-admin/generating-certificates/"}>Generate Certificates for Spinnaker&lt;/a> guide.&lt;/p>
&lt;h2 id="configuring-java-services">Configuring Java services&lt;/h2>
&lt;p>Add the following to each Java service profile under &lt;code>profiles&lt;/code> in the &lt;a href="/continuous-deployment/installation/armory-operator/op-config-manifest/#specspinnakerconfigprofiles">SpinnakerService&amp;rsquo;s profiles&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Only needed for &amp;#34;server&amp;#34; role&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: &amp;lt;reference to [service].p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-password&lt;/span>: &amp;lt;[SERVICE]_KEY_PASS&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Needed for all Java services&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">ok-http-client&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: &amp;lt;reference to truststore.p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-password&lt;/span>: &amp;lt;TRUSTSTORE_PASS&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store&lt;/span>: &amp;lt;reference to truststore.p12&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-type&lt;/span>: PKCS12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-password&lt;/span>: &amp;lt;TRUSTSTORE_PASS&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Currently, &lt;code>ok-http-client.key-store&lt;/code> is required even though it is not used in a simple TLS setup.&lt;/p>
&lt;/blockquote>
&lt;h2 id="configuring-golang-services">Configuring Golang services&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">certFile&lt;/span>: &amp;lt;reference to [service].crt&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyFile&lt;/span>: &amp;lt;reference to [service].key if not included in the certFile&amp;#39;s PEM&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyPassword&lt;/span>: &amp;lt;[GOSERVICE]_KEY_PASS if required&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">http&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cacertFile&lt;/span>: &amp;lt;reference to ca.pem&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="changing-service-endpoints">Changing service endpoints&lt;/h2>
&lt;p>Use the Operator to change Spinnaker&amp;rsquo;s service endpoints.&lt;/p>
&lt;p>Change the SpinnakerService custom resource:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">service-settings&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clouddriver&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-clouddriver.&amp;lt;NAMESPACE&amp;gt;:7002
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dinghy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-dinghy.&amp;lt;NAMESPACE&amp;gt;:8081
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">echo&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-echo.&amp;lt;NAMESPACE&amp;gt;:8089
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">fiat&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-fiat.&amp;lt;NAMESPACE&amp;gt;:7003
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">front50&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-front50.&amp;lt;NAMESPACE&amp;gt;:8080
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">gate&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-gate.&amp;lt;NAMESPACE&amp;gt;:8084
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kayenta&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-kayenta.&amp;lt;NAMESPACE&amp;gt;:8090
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">orca&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-orca.&amp;lt;NAMESPACE&amp;gt;:8083
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">igor&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-igor.&amp;lt;NAMESPACE&amp;gt;:8088
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rosco&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-rosco.&amp;lt;NAMESPACE&amp;gt;:8087
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">terraformer&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">baseUrl&lt;/span>: https://spin-terraformer.&amp;lt;NAMESPACE&amp;gt;:7088
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;h2 id="deploying-spinnaker">Deploying Spinnaker&lt;/h2>
&lt;p>After you finish modifying the service YAML files, run &lt;code>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;&lt;/code> to apply your changes to your Spinnaker deployment.&lt;/p>
&lt;p>Switching from plain HTTP to HTTPS will cause some short disruption to the services as they become healthy at different times.&lt;/p>
&lt;h2 id="providing-certificates-and-passwords-to-services">Providing certificates and passwords to services&lt;/h2>
&lt;h3 id="secret-engines">Secret engines&lt;/h3>
&lt;p>You can store secrets (and non secrets) in &lt;a href="/continuous-deployment/armory-admin/secrets/">supported secret stores&lt;/a> as well as in Kubernetes secrets if using the &lt;a href="/continuous-deployment/installation/armory-operator/">Armory Operator&lt;/a>. This is the simplest route.&lt;/p>
&lt;p>For instance, assuming all the information is stored in a bucket named &lt;code>mybucket&lt;/code> on s3 that all services have access to, &lt;code>SpinnakerService&lt;/code> manifest might look like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">profiles&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">echo&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: encryptedFile:s3!b:mybucket!r:us-west-2!f:echo.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-type&lt;/span>: JKS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-alias&lt;/span>: echo
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-password&lt;/span>: encrypted:s3!b:mybucket!r:us-west-2!f:passwords.yml!k:echo.keyPassword
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ok-http-client&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: encryptedFile:s3!b:mybucket!r:us-west-2!f:truststore.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-type&lt;/span>: JKS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store-password&lt;/span>: encrypted:s3!b:mybucket!r:us-west-2!f:passwords.yml!k:truststorePassword
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store&lt;/span>: encryptedFile:s3!b:mybucket!r:us-west-2!f:truststore.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-type&lt;/span>: JKS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trust-store-password&lt;/span>: encrypted:s3!b:mybucket!r:us-west-2!f:passwords.yml!k:truststorePassword
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Run &lt;code>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;&lt;/code> after you make your changes.&lt;/p>
&lt;h3 id="manually-providing-information">Manually providing information&lt;/h3>
&lt;p>An alternative if you cannot use one of the supported secret engine is to store the information in Kubernetes secrets and manually provide the information. Files are added through a &lt;code>volumeMount&lt;/code> and passwords through an environment variable.&lt;/p>
&lt;p>For instance, assuming &lt;code>mysecrets&lt;/code> Kubernetes Secret is available in the same namespace as Spinnaker with the following keys:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">data&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">echo.jks&lt;/span>: &amp;lt;base64 encoded keystore&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We&amp;rsquo;ll now provide the following in &lt;code>service-settings/echo.yml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kubernetes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">volume&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: secretvol
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">mountPath&lt;/span>: /var/mysecrets
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And a reference would then be:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">server&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">key-store&lt;/span>: /var/mysecrets/echo.jks
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Apply your changes.&lt;/p></description></item><item><title>Continuous-Deployment: Connect Docker Registries</title><link>/continuous-deployment/armory-admin/artifacts-docker-connect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/artifacts-docker-connect/</guid><description>
&lt;h2 id="overview-of-connecting-spinnaker-to-docker-registries">Overview of connecting Spinnaker to Docker registries&lt;/h2>
&lt;p>Many of the commands below have additional options that may be useful, or
possibly required.&lt;/p>
&lt;h2 id="enable-docker-registries-in-spinnaker">Enable Docker registries in Spinnaker&lt;/h2>
&lt;p>If you&amp;rsquo;ve just installed Armory or Open Source Spinnaker&lt;sup>TM&lt;/sup>, you need to enable Docker registry providers.&lt;/p>
&lt;p>Add the following snippet to &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">providers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dockerRegistry&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="add-a-docker-registry-and-repositories-to-spinnaker">Add a Docker registry and repositories to Spinnaker&lt;/h3>
&lt;p>To add a new registry, you use some variation of the following configuration.
This example uses a public Docker Hub registry (armory/demoapp) and actually
would not use the &lt;code>username&lt;/code> or &lt;code>password&lt;/code> options, since the registry is
public. In most cases, you&amp;rsquo;ll be configuring a private registry and the
authentication credentials will be required, so the options are shown here
as an example.&lt;/p>
&lt;p>Add the following snippet to &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">providers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">dockerRegistry&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">primaryAccount&lt;/span>: my-docker-registry &lt;span style="color:#6272a4"># Account with search priority. (Required when using a locally deployed registry.)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: my-docker-registry
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">requiredGroupMembership&lt;/span>: [] &lt;span style="color:#6272a4"># A user must be a member of at least one specified group in order to make changes to this account&amp;#39;s cloud resources.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">providerVersion&lt;/span>: V1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">permissions&lt;/span>: {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">address: https://index.docker.io # The registry address you want to pull and deploy images from. For example&lt;/span>: index.docker.io - DockerHub quay.io - Quay gcr.io - Google Container Registry (GCR) [us|eu|asia].gcr.io - Regional GCR localhost - Locally deployed registry
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">username&lt;/span>: yourusername &lt;span style="color:#6272a4"># Your docker registry username&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">password&lt;/span>: abc &lt;span style="color:#6272a4"># Your docker registry password. This field support &amp;#34;encrypted&amp;#34; secret references.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">email&lt;/span>: fake.email@spinnaker.io &lt;span style="color:#6272a4"># Your docker registry email (often this only needs to be well-formed, rather than be a real address)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cacheIntervalSeconds&lt;/span>: &lt;span style="color:#bd93f9">30&lt;/span> &lt;span style="color:#6272a4"># How many seconds elapse between polling your docker registry. Certain registries are sensitive to over-polling, and larger intervals (e.g. 10 minutes = 600 seconds) are desirable if you&amp;#39;re seeing rate limiting.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientTimeoutMillis&lt;/span>: &lt;span style="color:#bd93f9">60000&lt;/span> &lt;span style="color:#6272a4"># Timeout time in milliseconds for this repository.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cacheThreads&lt;/span>: &lt;span style="color:#bd93f9">1&lt;/span> &lt;span style="color:#6272a4"># How many threads to cache all provided repos on. Really only useful if you have a ton of repos.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">paginateSize&lt;/span>: &lt;span style="color:#bd93f9">100&lt;/span> &lt;span style="color:#6272a4"># Paginate size for the docker repository _catalog endpoint.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sortTagsByDate&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span> &lt;span style="color:#6272a4"># Sort tags by creation date.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trackDigests&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span> &lt;span style="color:#6272a4"># Track digest changes. This is not recommended as it consumes a high QPM, and most registries are flaky.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">insecureRegistry&lt;/span>: &lt;span style="color:#ff79c6">false&lt;/span> &lt;span style="color:#6272a4"># Treat the docker registry as insecure (don&amp;#39;t validate the ssl cert).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># repositories: # An optional list of repositories to cache images from. If not provided, Spinnaker will attempt to read accessible repositories from the registries _catalog endpoint&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># repositoriesRegex: &amp;lt;regexForYourRepos&amp;gt; # Optional regular expression that specifies what repositories Clouddriver caches images from. This is useful if you add repos frequently. Any new repo that matches the regex gets cached automatically.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - library/nginx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># passwordFile: docker-pass # The path to a file containing your docker password in plaintext (not docker/config.json file). This field support &amp;#34;encryptedFile&amp;#34; secret references.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># passwordCommand: abc # Command to retrieve docker token/password, commands must be available in environment&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># environment: dev # The environment name for the account. Many accounts can share the same environmen(e.g. dev, test, prod)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Some registries, like Docker Hub, require you to identify the
repositories explicitly, like above. Some do not (such as the Google
Container Registry). You can read more in the Spinnaker &lt;a href="https://www.spinnaker.io/setup/install/providers/docker-registry/">docs&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>Amazon&amp;rsquo;s ECR requires additional configuration to work properly with Spinnaker.
See the &lt;a href="/continuous-deployment/armory-admin/aws/artifacts-ecr-connect/"}>Connect Spinnaker to Amazon Elastic Container Registry&lt;/a> guide for details.&lt;/p></description></item><item><title>Continuous-Deployment: Connect Spinnaker to Jenkins</title><link>/continuous-deployment/armory-admin/jenkins-connect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/jenkins-connect/</guid><description>
&lt;blockquote>
&lt;p>Consult the Spinnaker documentation&amp;rsquo;s &lt;a href="https://www.spinnaker.io/setup/ci/jenkins/">Jenkins page&lt;/a> for an in-depth guide.&lt;/p>
&lt;/blockquote>
&lt;h2 id="enable-jenkins-in-spinnaker">Enable Jenkins in Spinnaker&lt;/h2>
&lt;p>Add the following snippet to your &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ci&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jenkins&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="create-a-user-api-token-in-jenkins">Create a User API Token in Jenkins&lt;/h2>
&lt;p>Spinnaker uses your Jenkins username and API token for authentication.&lt;/p>
&lt;ol>
&lt;li>Log into Jenkins&lt;/li>
&lt;li>Click on your username (in the top right)&lt;/li>
&lt;li>Click on &amp;ldquo;Configure&amp;rdquo; (on the left)&lt;/li>
&lt;li>Under the &amp;ldquo;API Token&amp;rdquo; section, click on &amp;ldquo;Add new Token&amp;rdquo;, and &amp;ldquo;Generate&amp;rdquo; and record the generated token&lt;/li>
&lt;li>Record your username; this is the value in the current page URL between &amp;lsquo;user&amp;rsquo; and &amp;lsquo;configure&amp;rsquo; (http://&lt;jenkins-url>/user/&lt;username>/configure)&lt;/li>
&lt;/ol>
&lt;h2 id="add-a-jenkins-master">Add a Jenkins Master&lt;/h2>
&lt;p>You can add as many Jenkins masters as needed. Once the master is configured
properly, Spinnaker will use the credentials provided to query for all
available jobs and display them in the UI for triggers and stages.&lt;/p>
&lt;p>Add the Jenkins master to Spinnaker:&lt;/p>
&lt;p>Add the following snippet to your &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ci&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">jenkins&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">masters&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: &amp;lt;jenkins-master-name&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">address&lt;/span>: https://&amp;lt;jenkins-url&amp;gt;/ &lt;span style="color:#6272a4"># The address your jenkins master is reachable at.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">username&lt;/span>: &amp;lt;jenkins-username&amp;gt; &lt;span style="color:#6272a4"># The username of the jenkins user to authenticate as.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">password&lt;/span>: abc &lt;span style="color:#6272a4"># The password of the jenkins user to authenticate as. This field support &amp;#34;encrypted&amp;#34; secret references.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Don&amp;rsquo;t forget to apply your changes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;gt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="troubleshooting-authentication--connectivity">Troubleshooting Authentication / Connectivity&lt;/h2>
&lt;p>Igor is the service that interacts with Jenkins. You can test Spinnaker-Jenkins connectivity using &lt;code>curl&lt;/code> from another pod. The Deck or Clouddriver pod is a good option since &lt;code>curl&lt;/code> is already installed there.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl https://&amp;lt;jenkins-url&amp;gt;/api/json --user &amp;lt;jenkins-username&amp;gt;:&amp;lt;jenkins-api-token&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This returns a JSON list of jobs.&lt;/p>
&lt;p>For example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Exec into the Clouddriver container:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl &lt;span style="color:#8be9fd;font-style:italic">exec&lt;/span> -it spin-clouddriver-6cf45f4db-lkg7t bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>bash-4.4$ curl https://jenkins.domain.com/api/json --user justin:1234567890abcdefghijklmnopqrstuvwx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">{&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;_class&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;hudson.model.Hudson&amp;#34;&lt;/span>,&lt;span style="color:#f1fa8c">&amp;#34;assignedLabels&amp;#34;&lt;/span>:&lt;span style="color:#ff79c6">[{&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;name&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;master&amp;#34;&lt;/span>&lt;span style="color:#ff79c6">}]&lt;/span>, &lt;span style="color:#ff79c6">[&lt;/span>...&lt;span style="color:#ff79c6">]&lt;/span> &lt;span style="color:#ff79c6">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Continuous-Deployment: Connect GitHub as an Artifact Source in Spinnaker</title><link>/continuous-deployment/armory-admin/artifacts-github-connect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/artifacts-github-connect/</guid><description>
&lt;h2 id="configure-a-github-trigger-in-spinnaker">Configure a GitHub trigger in Spinnaker&lt;/h2>
&lt;p>Spinnaker&lt;sup>TM&lt;/sup> pipelines can be configured to trigger when a change is committed to a GitHub repository. This doesn&amp;rsquo;t require any configuration of Spinnaker other than &lt;a href="/continuous-deployment/spinnaker-user-guides/artifacts-github-use/">adding a GitHub trigger&lt;/a> but does require administration of the GitHub repositories to configure the webhook.&lt;/p>
&lt;p>The open source Spinnaker documentation
&lt;a href="https://www.spinnaker.io/setup/triggers/github/">has concise instructions for configuring GitHub webhooks.&lt;/a>&lt;/p>
&lt;h2 id="configure-github-as-an-artifact-source">Configure GitHub as an artifact source&lt;/h2>
&lt;p>If you actually want to use a file from the GitHub commit in your pipeline,
you&amp;rsquo;ll need to configure GitHub as an artifact source in Spinnaker.&lt;/p>
&lt;p>Many of the commands below have additional options that may be useful (or
possibly required).&lt;/p>
&lt;h3 id="enable-github-artifacts">Enable GitHub artifacts&lt;/h3>
&lt;p>If you haven&amp;rsquo;t done this yet (for example, if you&amp;rsquo;ve just installed Armory
Spinnaker fresh), you need to enable GitHub as an artifact source:&lt;/p>
&lt;p>Add the following snippet to &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">features&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">artifacts&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">artifacts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">github&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="add-a-github-credential">Add a GitHub credential&lt;/h3>
&lt;p>To access private GitHub repositories, you need a GitHu b&lt;strong>Personal Access
Token&lt;/strong>. See the &lt;a href="https://docs.github.com/en/enterprise-server@3.4/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token">GitHub docs&lt;/a> for instructions. The token
needs the &lt;code>repo&lt;/code> scope.&lt;/p>
&lt;p>Once you have a token, you should provide that token for Spinnaker&amp;rsquo;s Igor service
as a credential to use to access GitHub.&lt;/p>
&lt;blockquote>
&lt;p>Replace the account name &lt;code>github_user&lt;/code> with the string you want to use to identify this GitHub credential.&lt;/p>
&lt;/blockquote>
&lt;p>Add the following snippet to &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">features&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">artifacts&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">artifacts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">github&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: github_user
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">token&lt;/span>: abc &lt;span style="color:#6272a4"># GitHub&amp;#39;s personal access token. This fields supports `encrypted` references to secrets.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># username: abc # GitHub username&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># password: abc # GitHub password. This fields supports `encryptedreferences` to secrets.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># usernamePasswordFile: creds.txt # File containing &amp;#34;username:password&amp;#34; to use for GitHub authentication. This fields supports `encryptedFilereferences` to secrets.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># tokenFile: token.txt # File containing a GitHub authentication token. This fields supports `encryptedFile` references to secrets.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you have a GitHub Personal Access Token, you only need that to authenticate against GitHub, but there are other authentication options like username/password, or specifying credentials in a &lt;code>file&lt;/code> entry.&lt;/p>
&lt;p>Apply your changes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;gt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="using-the-github-credential">Using the GitHub credential&lt;/h2>
&lt;p>You may note that the above GitHub &amp;ldquo;account&amp;rdquo; doesn&amp;rsquo;t actually have an endpoint for
your GitHub. This account is basically just the credential used by Spinnaker
artifacts to access GitHub. The actual GitHub API endpoint is specified in the
artifact reference. The following is an example of how to use this credential.&lt;/p>
&lt;p>&lt;strong>Pulling a Kubernetes Manifest from Github&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Under &lt;strong>Expected Artifacts&lt;/strong> in your pipeline, create an artifact of type &lt;strong>GitHub&lt;/strong>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Specify the &lt;strong>file path&lt;/strong> as the path within the repository to your file. For example, if your manifest is at &lt;code>demo/manifests/deployment.yml&lt;/code> in the Github repository &lt;code>orgname/reponame&lt;/code> , specify &lt;code>demo/manifests/deployment.yml&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Check the &lt;strong>Use Default Artifact&lt;/strong> checkbox.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>In the &lt;strong>Content URL&lt;/strong>, provide the full path to the &lt;em>API URI&lt;/em> for your manifest. Here are some examples of this:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>If you&amp;rsquo;re using SaaS GitHub, the URI is generally formatted like this: &lt;code>https://api.github.com/repos/&amp;lt;ORG&amp;gt;/&amp;lt;REPO&amp;gt;/contents/&amp;lt;PATH-TO-FILE&amp;gt;&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>For example: &lt;code>https://api.github.com/repos/armory/demo/contents/manifests/deployment.yml&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>If you have on-prem Github Enterprise, then the URI may be formatted like this: &lt;code>https://&amp;lt;GITHUB_URL&amp;gt;/api/v3/repos/&amp;lt;ORG&amp;gt;/&amp;lt;REPO&amp;gt;/contents/&amp;lt;PATH-TO-FILE&amp;gt;&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>For example: &lt;code>http://github.customername.com/api/v3/repos/armory/spinnaker-pipelines/contents/manifests/deployment.yml&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Create a &lt;strong>Deploy (Manifest)&lt;/strong> stage. Rather than specifying the manifest directly in the UI, under the &lt;strong>Manifest Source&lt;/strong> specify &lt;strong>Artifact&lt;/strong>, and in the &lt;strong>Expected Artifact&lt;/strong> field, select the artifact you created above.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If you have multiple Github Accounts (credentials) added to your Spinnaker cluster, there should be a dropdown to select which one to use.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="troubleshooting-credentials-and-uris">Troubleshooting credentials and URIs&lt;/h2>
&lt;p>To verify that your token and URI are correct, you can run a &lt;code>curl&lt;/code> command to
test authentication (the &lt;code>user&lt;/code> field doesn&amp;rsquo;t matter):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl https://api.github.com/repos/armory/demo/contents/manifests/deployment.yml &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -u nobody:abcdef0123456789abcdef0123456789abcdef01
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you receive metadata about your file, the credential and URI are correct.&lt;/p></description></item><item><title>Continuous-Deployment: Create Kubernetes Service Accounts and Kubeconfigs</title><link>/continuous-deployment/armory-admin/manual-service-account/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/manual-service-account/</guid><description>
&lt;h2 id="what-spinnaker-needs-to-connect-to-kubernetes">What Spinnaker needs to connect to Kubernetes&lt;/h2>
&lt;p>When connecting Spinnaker to Kubernetes, Spinnaker needs the following:&lt;/p>
&lt;ul>
&lt;li>A service account in the relevant Kubernetes cluster (or namespace in a cluster). &lt;em>In Kubernetes, a service account exists in a given namespace but may have access to other namespaces or to the whole cluster&lt;/em>&lt;/li>
&lt;li>Permissions for the service account to create/read/update/delete objects in the relevant Kubernetes cluster (or namespace)&lt;/li>
&lt;li>A kubeconfig that has access to the service account through a token or some other authentication method.&lt;/li>
&lt;/ul>
&lt;p>The &lt;a href="https://github.com/armory/spinnaker-tools">spinnaker-tools binary&lt;/a> creates all of the above objects. See &lt;a href="/continuous-deployment/armory-admin/kubernetes-account-add/"}>Add a Kubernetes Account Deployment Target in Spinnaker&lt;/a> if you want to use the &lt;code>spinnaker-tools&lt;/code> binary. Otherwise, if you want to create these objects manually or need to know what is going on, use this document.&lt;/p>
&lt;div class="alert alert-warning" role="alert">
&lt;h4 class="alert-heading">Attention&lt;/h4>
&lt;p>This document primarily uses &lt;code>kubectl&lt;/code> and assumes you have access to permissions that can create and/or update these resources in your Kubernetes cluster:&lt;/p>
&lt;ul>
&lt;li>Kubernetes Service Account(s)&lt;/li>
&lt;li>Kubernetes Roles and Rolebindings&lt;/li>
&lt;li>(Optionally) Kubernetes ClusterRoles and Rolebindings&lt;/li>
&lt;/ul>
&lt;/div>
&lt;h2 id="create-the-kubernetes-service-account">Create the Kubernetes Service Account&lt;/h2>
&lt;p>You can use the following manifest to create a service account. Replace &lt;code>NAMESPACE&lt;/code> with the namespace you want to use and, optionally, rename the service account.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># spinnaker-service-account.yml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: ServiceAccount
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-service-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">namespace&lt;/span>: NAMESPACE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then create the object:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl apply -f spinnaker-service-account.yml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="grant-cluster-admin-permissions">Grant &lt;code>cluster-admin&lt;/code> permissions&lt;/h2>
&lt;blockquote>
&lt;p>Do this only if you want to grant the service account access to all namespaces in your cluster. A Kubernetes ClusterRoleBinding exists at the cluster level, but the &lt;em>subject&lt;/em> of the ClusterRoleBinding exists in a single namespace. Again, you &lt;em>must&lt;/em> specify the namespace where your service account lives.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># spinnaker-clusterrolebinding.yml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1beta1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: ClusterRoleBinding
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-admin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">roleRef&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiGroup&lt;/span>: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kind&lt;/span>: ClusterRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: cluster-admin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">subjects&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ff79c6">kind&lt;/span>: ServiceAccount
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-service-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">namespace&lt;/span>: NAMESPACE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, create the binding:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl apply -f spinnaker-clusterrolebinding.yml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="grant-namespace-specific-permissions">Grant namespace-specific permissions&lt;/h2>
&lt;p>If you only want the service account to access specific namespaces, you can create a role with a set of permissions and &lt;code>rolebinding&lt;/code> to attach the role to the service account. You can do this multiple times. Additionally, you will have to explicitly do this for the namespace where the service account is, as it is not implicit.&lt;/p>
&lt;p>Important points:&lt;/p>
&lt;ul>
&lt;li>A Kubernetes &lt;code>Role&lt;/code> exists in a given namespace and grants access to items in that namespace&lt;/li>
&lt;li>A Kubernetes &lt;code>RoleBinding&lt;/code> exists in a given namespace and attaches a role in that namespace to some principal (in this case, a service account). The principal (service account) may be in another namespace.&lt;/li>
&lt;li>If you have a service account in namespace &lt;code>source&lt;/code> and want to grant access to namespace &lt;code>target&lt;/code>, then do the following:
&lt;ul>
&lt;li>Create the service account in namespace &lt;code>source&lt;/code>&lt;/li>
&lt;li>Create a Role in namespace &lt;code>target&lt;/code>&lt;/li>
&lt;li>Create a RoleBinding in namespace &lt;code>target&lt;/code>, with the following properties:
&lt;ul>
&lt;li>RoleRef pointing to the Role (that is in the same namespace &lt;code>target&lt;/code>)&lt;/li>
&lt;li>Subject pointing to the service account and namespace where the service account lives (in namespace &lt;code>source&lt;/code>)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Change the names of resources to match your environment, as long as the namespaces are correct, and the subject name and namespace match the name and namespace of your service account.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># spinnaker-role-and-rolebinding-target.yml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: Role
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-role
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">namespace&lt;/span>: target &lt;span style="color:#6272a4"># Should be namespace you are granting access to&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">rules&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ff79c6">apiGroups&lt;/span>: [&lt;span style="color:#f1fa8c">&amp;#34;*&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">resources&lt;/span>: [&lt;span style="color:#f1fa8c">&amp;#34;*&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">verbs&lt;/span>: [&lt;span style="color:#f1fa8c">&amp;#34;*&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: RoleBinding
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-rolebinding
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">namespace&lt;/span>: target &lt;span style="color:#6272a4"># Should be namespace you are granting access to&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">roleRef&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiGroup&lt;/span>: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kind&lt;/span>: Role
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-role &lt;span style="color:#6272a4"># Should match name of Role&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">subjects&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ff79c6">namespace&lt;/span>: source &lt;span style="color:#6272a4"># Should match namespace where SA lives&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">kind&lt;/span>: ServiceAccount
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker-service-account &lt;span style="color:#6272a4"># Should match service account name, above&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, create the object:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl apply -f spinnaker-role-and-rolebinding-target.yml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="get-the-service-account-and-token">Get the service account and token&lt;/h2>
&lt;p>Run these commands (or commands like these) to get the token for your service account and create a kubeconfig with access to the service account.&lt;/p>
&lt;p>&lt;strong>&lt;em>This file will contain credentials for your Kubernetes cluster and should be stored securely.&lt;/em>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Update these to match your environment&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">SERVICE_ACCOUNT_NAME&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>spinnaker-service-account
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>kubectl config current-context&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">NEW_CONTEXT&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;kubeconfig-sa&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">SECRET_NAME&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>kubectl get serviceaccount &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SERVICE_ACCOUNT_NAME&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --namespace &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -o &lt;span style="color:#8be9fd;font-style:italic">jsonpath&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;{.secrets[0].name}&amp;#39;&lt;/span>&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">TOKEN_DATA&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>kubectl get secret &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">SECRET_NAME&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --namespace &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -o &lt;span style="color:#8be9fd;font-style:italic">jsonpath&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#39;{.data.token}&amp;#39;&lt;/span>&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">TOKEN&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">TOKEN_DATA&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> | base64 -d&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Create dedicated kubeconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Create a full copy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl config view --raw &amp;gt; &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.full.tmp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Switch working context to correct context&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.full.tmp config use-context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Minify&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.full.tmp &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> config view --flatten --minify &amp;gt; &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Rename context&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl config --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> rename-context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NEW_CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Create token user&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl config --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> set-credentials &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>-&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>-token-user &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --token &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">TOKEN&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Set context to use token user&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl config --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> set-context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NEW_CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> --user &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>-&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>-token-user
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Set context to correct namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl config --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> set-context &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NEW_CONTEXT&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> --namespace &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Flatten/minify kubeconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl config --kubeconfig &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> view --flatten --minify &amp;gt; &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Remove tmp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.full.tmp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">KUBECONFIG_FILE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.tmp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You should end up with a kubeconfig that can access your Kubernetes cluster with the desired target namespaces.&lt;/p></description></item><item><title>Continuous-Deployment: DNS and SSL</title><link>/continuous-deployment/armory-admin/dns-and-ssl/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/dns-and-ssl/</guid><description>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>In order to use Spinnaker in your organization, you&amp;rsquo;re going to want to configure your infrastructure so that users can access Spinnaker. This has several steps:&lt;/p>
&lt;ul>
&lt;li>Expose the Spinnaker endpoints (Deck and Gate)&lt;/li>
&lt;li>Configure TLS encryption for the exposed endpoints&lt;/li>
&lt;li>Create DNS entries for your endpoints&lt;/li>
&lt;li>Update Spinnaker so that it&amp;rsquo;s aware of its new endpoints.&lt;/li>
&lt;/ul>
&lt;h2 id="expose-the-spinnaker-endpoints">Expose the Spinnaker endpoints&lt;/h2>
&lt;p>Spinnaker users need access to two endpoints within Spinnaker&lt;/p>
&lt;ul>
&lt;li>Deck (the Spinnaker UI microservice), which listens on port 9000&lt;/li>
&lt;li>Gate (the spinnaker API microservice), which listens on port 8084&lt;/li>
&lt;/ul>
&lt;p>There are a number of ways to expose these endpoints, and your configuration of these will be heavily dependent on the Kubernetes environment where Spinnaker is installed. Several common options are as follows:&lt;/p>
&lt;ul>
&lt;li>Set up an ALB ingress controller within your Kubernetes environment, and add an ingress for the &lt;code>spin-deck&lt;/code> and &lt;code>spin-gate&lt;/code> services.&lt;/li>
&lt;li>Set up an nginx ingress controller within your Kubernetes environment, and add an ingress for the &lt;code>spin-deck&lt;/code> and &lt;code>spin-gate&lt;/code> services.&lt;/li>
&lt;li>Create Kubernetes &lt;code>loadbalancer&lt;/code> services for both the &lt;code>spin-deck&lt;/code> and &lt;code>spin-gate&lt;/code> Kubernetes deployments&lt;/li>
&lt;/ul>
&lt;h2 id="configure-tls-encryption-for-the-exposed-endpoints">Configure TLS encryption for the exposed endpoints&lt;/h2>
&lt;p>You should encrypt the exposed Spinnaker endpoints. There are three high-level ways of achieving this:&lt;/p>
&lt;ul>
&lt;li>Most common: Terminate TLS on the load balancer(s) in front of the endpoints, and allow HTTP traffic between the load balancer and the endpoint backends.&lt;/li>
&lt;li>Terminate TLS on the load balancer(s) in front of the endpoints, and configure the load balancer and endpoint backends with TLS between them, as well.&lt;/li>
&lt;li>Least common: Configure your load balancer(s) to support the SNI so that the load balancer passes the initial TLS connection to the backends.&lt;/li>
&lt;/ul>
&lt;p>There are a number of ways to achieve all of these - you can work with your Kubernetes, security, and networking teams to determine which methods best meet your organization&amp;rsquo;s needs.&lt;/p>
&lt;p>If you need to terminate TLS on the backend containers (the second or third options), review the Open Source Spinnaker documentation regarding configuring TLS certificates on the backend microservices: (Setup/Security/SSL)[https://spinnaker.io/setup/security/ssl/].&lt;/p>
&lt;h2 id="create-a-dns-entry-for-your-load-balancer">Create a DNS Entry for your load balancer&lt;/h2>
&lt;p>Add a DNS Entry to your DNS management system. You should only need to add a DNS entry for the user-facing ALB, ELB, or other load balancer which is what you use to currently access Spinnaker. It typically has a name such as the one below&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>armoryspinnaker-prod-external-123456789.us-west-1.elb.amazonaws.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Add a CNAME entry for the given ELB to create a simple name you will use to access your instance of Spinnaker, e.g. &lt;code>spinnaker.armory.io&lt;/code>.&lt;/p>
&lt;h2 id="update-spinnaker-configuration">Update Spinnaker configuration&lt;/h2>
&lt;p>Update the endpoints for Spinnaker Deck (the Spinnaker UI microservice) and Spinnaker Gate (the Spinnaker API microservice)&lt;/p>
&lt;!-- markdown-link-check-disable -->
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">overrideBaseUrl&lt;/span>: https://spinnaker-gate.mydomain.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">uiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">overrideBaseUrl&lt;/span>: https://spinnaker.mydomain.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- markdown-link-check-enable-->
&lt;p>Don&amp;rsquo;t forget to apply your changes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Continuous-Deployment: Enable Pipelines-as-Code in Armory Continuous Deployment</title><link>/continuous-deployment/armory-admin/pipelines-as-code-enable/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/pipelines-as-code-enable/</guid><description/></item><item><title>Continuous-Deployment: Enable the Evaluate Artifacts Stage</title><link>/continuous-deployment/armory-admin/evaluate-artifacts-stage-enable/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/evaluate-artifacts-stage-enable/</guid><description>
&lt;p>&lt;img src="/images/proprietary.svg" alt="Proprietary">&lt;/p>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>Some artifact types and their associated stages, such as Kubernetes, support using SpEL to read parameters from the Spinnaker context and inject them into an artifacts manifest at deploy time. Other stages, such as the Terraform Integration stage, do not support this out of the box. The Evaluate Artifacts Stage plugin adds supports for evaluating SpEL against any artifact within your Spinnaker pipeline.&lt;/p>
&lt;p>For information about how to use the stage, see &lt;a href="/continuous-deployment/spinnaker-user-guides/evaluate-artifacts-stage-use/"}>Use the Evaluate Artifacts Stage&lt;/a>.&lt;/p>
&lt;h2 id="before-you-begin">Before you begin&lt;/h2>
&lt;ul>
&lt;li>If you are new to enabling plugins, read Spinnaker&amp;rsquo;s &lt;a href="https://spinnaker.io/docs/guides/user/plugins-users/">Plugin Users Guide&lt;/a> to familiarize yourself with how plugins to Armory Continuous Deployment work.&lt;/li>
&lt;li>The Evaluate Artifacts Stage requires Armory Continuous Deployment 2.24.x or later (Spinnaker 1.24.x or later)&lt;/li>
&lt;/ul>
&lt;h2 id="setup">Setup&lt;/h2>
&lt;p>Add the following snippet to your Spinnaker manifest, such as &lt;code>spinnakerservice.yml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">profiles&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnaker&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnaker&lt;/span>: &lt;span style="color:#6272a4"># This second `spinnaker` is required&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">extensibility&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">plugins&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">Armory.EvaluateArtifactsPlugin&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">version&lt;/span>: &amp;lt;PLUGIN_VERSION&amp;gt; &lt;span style="color:#6272a4"># Replace with the version you want to use. For example, use 0.1.0.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">repositories&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">evaluateArtifacts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">url&lt;/span>: https://raw.githubusercontent.com/armory-plugins/evaluate-artifacts-releases/master/repositories.json
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">gate&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnaker&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">extensibility&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">deck-proxy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">plugins&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">Armory.EvaluateArtifactsPlugin&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">version&lt;/span>: &amp;lt;PLUGIN_VERSION&amp;gt; &lt;span style="color:#6272a4"># Replace with the version you want to use. For example, use 0.1.0.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Keep the following in mind when using this configuration snippet:&lt;/p>
&lt;ul>
&lt;li>Make sure to include the nested &lt;code>spinnaker&lt;/code> parameter. Both are required because of how Armory Continuous Deployment consumes plugin configurations.&lt;/li>
&lt;li>Replace &lt;code>&amp;lt;PLUGIN_VERSION&amp;gt;&lt;/code> on lines 10 and 22 with the version of the plugin that you want to use. Plugin versions can be found &lt;a href="#versions">here&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Then, deploy your updated Armory Continuous Deployment configuration using one of the following methods:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>If you are using a single manifest file: &lt;code>kubectl -n &amp;lt;namespace&amp;gt; apply -f &amp;lt;path-to-manifest-file&amp;gt;&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If you are using Kustomize patches like the ones in the &lt;a href="https://github.com/armory/spinnaker-kustomize-patches">Armory kustomize repo&lt;/a>, you need to apply the kustomization. Depending on how you have Kustomize installed (either directly or as part of &lt;code>kubectl&lt;/code>), use one of the following commands:&lt;/p>
&lt;p>Kustomize is installed separately from &lt;code>kubectl&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># The namespace is declared in kustomization.yml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Run this from the same directory as your kustomization.yml file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kustomize build | kubectl apply -f -
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Kustomize is bundled with &lt;code>kubectl&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubctl -n &amp;lt;namespace&amp;gt; apply -k &amp;lt;path-to-kustomize-directory&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h2 id="versions">Versions&lt;/h2>
&lt;ul>
&lt;li>0.1.1 - Update plugin to be compatible with Armory Continuous Deployment 2.27.0 and later&lt;/li>
&lt;li>0.1.0 - Improved the user experience. Execution errors for the stage now display in the UI.&lt;/li>
&lt;li>0.0.10 - Initial Release&lt;/li>
&lt;/ul>
&lt;h2 id="whats-next">What&amp;rsquo;s next&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="/continuous-deployment/spinnaker-user-guides/evaluate-artifacts-stage-use/"}>Use the Evaluate Artifacts Stage&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Continuous-Deployment: Enable the Terraform Integration Stage in Armory Continuous Deployment</title><link>/continuous-deployment/armory-admin/terraform-enable-integration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/terraform-enable-integration/</guid><description/></item><item><title>Continuous-Deployment: Expose Spinnaker API Endpoints</title><link>/continuous-deployment/armory-admin/api-endpoint/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/api-endpoint/</guid><description>
&lt;h2 id="overview-of-setting-up-an-x509-client-certificate-for-spinnaker">Overview of setting up an X509 client certificate for Spinnaker&lt;/h2>
&lt;p>When you have third-party authentication set up for your Spinnaker&lt;sup>TM&lt;/sup> cluster, automating against the Spinnaker API can be slightly more difficult. One way to achieve this is to set up X509 client certificate authentication, which can optionally be enabled on a second port on Gate (which then must be exposed to clients). This document details one way to do this.&lt;/p>
&lt;p>This document details the following:&lt;/p>
&lt;ul>
&lt;li>Obtaining / Creating a CA certificate. If your organization has an internal (or other) CA, you can use the organization CA certificate (you only need the certificate in PEM format). All API clients must present a certificate signed by this CA; if you are creating a self-signed certificate, you can create client certs on your own. If you are using an organization CA, you must be able to request client certs from your organization CA.&lt;/li>
&lt;li>Obtaining / Creating a certificate and private key for use by Deck (Spinnaker&amp;rsquo;s UI microservice). You can either request the certificate from your organization&amp;rsquo;s CA, or use the self-signed CA created above.&lt;/li>
&lt;li>Obtaining / Creating a certificate and private key for use by Gate (Spinnaker&amp;rsquo;s UI microservice). You can either request the certificate from your organization&amp;rsquo;s CA, or use the self-signed CA created above.&lt;/li>
&lt;li>Creating a JKS (Java Keystore) for Gate containing these two objects:
&lt;ul>
&lt;li>The CA certificate imported as a trust store. Gate will use this to validate all inbound certificate-based clients. Specifically, this operates in this fashion:
&lt;ul>
&lt;li>Spinnaker only needs the certificate, not the private key. Generally speaking, the certificate is not a sensitive piece of information (it is what is publicly presented)&lt;/li>
&lt;li>This CA certificate can either be an organization-wide CA certificate, or a CA certificate built specifically for Spinnaker&lt;/li>
&lt;li>Gate (Spinnaker&amp;rsquo;s API layer) will trust clients that present a certificate signed by this certificate&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Gate&amp;rsquo;s server certificate and private key, which does not necessarily need to be a valid certificate if Gate is fronted by a load balancer&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Enabling Deck to use the certificate generated for Deck&lt;/li>
&lt;li>Enabling Gate to use the JKS&lt;/li>
&lt;li>Configuring Gate to support X509 client certificate-based authentication, on a second port.&lt;/li>
&lt;/ul>
&lt;h2 id="exposed-spinnaker-endpoints">Exposed Spinnaker endpoints&lt;/h2>
&lt;p>At the end of this process, you will have three exposed endpoints for Spinnaker:&lt;/p>
&lt;ul>
&lt;li>A UI endpoint on the Deck microservice. You can terminate TLS on the load balancer (Ingress or other load balancer), and end up with a flow that looks like this:
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span>Browser&lt;span style="color:#ff79c6">]&lt;/span> ---HTTPS--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>Load Balancer with TLS Termination&lt;span style="color:#ff79c6">]&lt;/span> ---HTTP--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>Deck:9000&lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>An API endpoint on the Gate microservice for browser clients. You can terminate TLS on the load balancer (Ingress or other load balancer). Authentication will be handled by your primary authentication provider (LDAP, SAML, OAuth2.0, etc.). You may end up with a flow that looks like this:
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span>Browser&lt;span style="color:#ff79c6">]&lt;/span> ---HTTPS--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>Load Balancer with TLS Termination&lt;span style="color:#ff79c6">]&lt;/span> ---HTTP--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>Gate:8084&lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>An API endpoint on the Gate microservice for automation clients. Clients must present an x509 client certificate in order to use this endpoint, so you &lt;em>cannot&lt;/em> terminate TLS on a load balancer in front of Gate. The data flow may look something like this:
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span>API Client&lt;span style="color:#ff79c6">]&lt;/span> ---HTTPS--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>TCP Load Balancer&lt;span style="color:#ff79c6">]&lt;/span> ---HTTPS--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>Gate:8085&lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>or
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span>API Client&lt;span style="color:#ff79c6">]&lt;/span> ---HTTPS--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>TLS Pass Through Load Balancer&lt;span style="color:#ff79c6">]&lt;/span> ---HTTPS--&amp;gt; &lt;span style="color:#ff79c6">[&lt;/span>Gate:8085&lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h2 id="decision-points">Decision points&lt;/h2>
&lt;p>Before moving on, you should decide the following:&lt;/p>
&lt;ul>
&lt;li>For the CA used to validate client certificates, are you using an organization CA or creating a self-signed CA?&lt;/li>
&lt;li>For the Gate and Deck certificate, are you using certificates signed by an organization CA, certificates signed by a self-signed CA, or self-signed certificates?&lt;/li>
&lt;li>In order to access the API endpoint, the API endpoint (which is an extra port on the existing Gate service) must be directly exposed. Clients must be able to provide their certificates to Gate; there should be no TLS termination in front of it. This means you must do one of the following:
&lt;ul>
&lt;li>Set up a Layer 4 (TCP) load balancer in front of this endpoint&lt;/li>
&lt;li>Set up a Layer 7 (HTTPS) load balancer that supports TLS passthrough.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>This document borrows heavily from the Open Source Spinnaker document on SSL, found here: &lt;a href="https://www.spinnaker.io/setup/security/ssl/">Setup / Security / SSL&lt;/a>.&lt;/p>
&lt;h2 id="getting-a-self-signed-ca-certificate">Getting a self-signed CA certificate&lt;/h2>
&lt;p>If your organization has a CA that you can use to sign client certificates, then you must obtain a copy of the CA certificate (note: this is generally the public-facing certificate, and therefore not sensitive information). You must get this in a PEM-formatted file, or convert it to a PEM-formatted file.&lt;/p>
&lt;p>Alternatively, you can create a self-signed CA certificate to use to sign client certificates, and configure Gate to trust certificates signed by this CA certificate.&lt;/p>
&lt;h3 id="obtaining-the-organization-certificate">Obtaining the organization certificate&lt;/h3>
&lt;p>If your organization has a CA certificate, you should obtain the CA certificate in PEM format. You do not need the private key, as long as your organization has a way to request client certificates signed by the CA.&lt;/p>
&lt;p>You should have the following items:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ca.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted certificate. Spinnaker will trust client certificates that were signed by this CA.&lt;/li>
&lt;/ul>
&lt;h3 id="creating-a-self-signed-ca-certificate">Creating a self-signed CA certificate&lt;/h3>
&lt;p>If your organization has a CA certificate or you do not have a way to request client certificates signed by the CA, you can generate a self-signed CA certificate and private key. We will use this&lt;/p>
&lt;p>We will use &lt;code>openssl&lt;/code> to generate a Certificate Authority (CA) key and a server
certificate. These instructions create a self-signed CA and key. You might want to
use an external CA, to minimize browser configuration, but it&amp;rsquo;s not necessary
(and can be expensive).&lt;/p>
&lt;p>Use the steps below to create a Certificate Authority. (If you&amp;rsquo;re using an
external CA, skip to the next section.)&lt;/p>
&lt;p>It will produce the following items:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ca.key&lt;/code>: a &lt;code>pem&lt;/code>-formatted private key, which will have a pass phrase.&lt;/li>
&lt;li>&lt;code>ca.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted certificate, which (with the private key) acts as
a self-signed Certificate Authority.&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>
&lt;p>Create the CA key, which will be encrypted with a passphrase. You can remove the &lt;code>-passout&lt;/code> flag to have the command prompt for the passphrase.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_CA_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl genrsa &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -des3 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out ca.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Self-sign the CA certificate. You can remove the &lt;code>-passin&lt;/code> flag to have the command prompt for the passphrase. This should be the pass phrase used to
encrypt &lt;code>ca.key&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_CA_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -new &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -x509 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -days &lt;span style="color:#bd93f9">365&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -key ca.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out ca.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;h2 id="get-a-server-certificate-for-the-deck-ui-service">Get a server certificate for the Deck (UI) service&lt;/h2>
&lt;blockquote>
&lt;p>This step is technically optional, but it requires setting up separate exposure mechanisms for Deck and Gate if this step is skipped. For simplicity&amp;rsquo; sake, we recommend completing this step.&lt;/p>
&lt;/blockquote>
&lt;p>You need a server certificate and private key. If you have a load balancer in front of Deck that is terminating TLS, the certificate on Deck generally won&amp;rsquo;t matter aside from the fact that you must have one. There are two main options here:&lt;/p>
&lt;ol>
&lt;li>Obtaining a server certificate and private key from your organization CA&lt;/li>
&lt;li>Generating a server certificate and private key from the self-signed CA&lt;/li>
&lt;/ol>
&lt;h3 id="obtaining-a-deck-server-certificate-and-private-key-from-your-organization-ca">Obtaining a Deck server certificate and private key from your organization CA&lt;/h3>
&lt;p>If your organization has a CA certificate, you should request a server certificate for use with Deck. This should result in the following files:&lt;/p>
&lt;ul>
&lt;li>&lt;code>deck.key&lt;/code>: a &lt;code>pem&lt;/code>-formatted private key, which will have a pass phrase.&lt;/li>
&lt;li>&lt;code>deck.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted x509 certificate, which matches the private key and was signed by your CA.&lt;/li>
&lt;/ul>
&lt;h3 id="generating-a-deck-server-certificate-and-private-key-from-the-self-signed-ca">Generating a Deck server certificate and private key from the self-signed CA&lt;/h3>
&lt;p>If you want to generate your own certificates (for example, from the self-signed CA certificate created above), you can follow these steps:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Create a server key for Deck. Keep this file safe!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This will be the passphrase used to encrypt the Deck private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">DECK_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_DECK_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl genrsa &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -des3 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out deck.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">DECK_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Generate a certificate signing request (CSR) for Deck. Specify &lt;code>localhost&lt;/code> or
Deck&amp;rsquo;s eventual fully-qualified domain name (FQDN) as the Common Name (CN).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the passphrase used to encrypt the Deck private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">DECK_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_DECK_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -new &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -key deck.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out deck.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">DECK_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Use the CA to sign the server&amp;rsquo;s request and create the Deck server certificate
(in &lt;code>pem&lt;/code> format). If using an external CA, they will do this for you.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the passphrase used to encrypt the self-signed CA private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_CA_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl x509 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -days &lt;span style="color:#bd93f9">365&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -in deck.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CA ca.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAkey ca.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAcreateserial &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out deck.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>You should end up with these two files:&lt;/p>
&lt;ul>
&lt;li>&lt;code>deck.key&lt;/code>: a &lt;code>pem&lt;/code>-formatted private key, which will have a pass phrase&lt;/li>
&lt;li>&lt;code>deck.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted x509 certificate, which matches the private key and was signed by your CA&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="get-a-server-certificate-for-the-gate-api-service">Get a server certificate for the Gate (API) Service&lt;/h2>
&lt;p>You will need a server certificate and private key. This server certificate will be used for both Gate endpoints - one for the authenticated API endpoint used by browser clients, one for the certificate-authenticated (X509) API endpoint used by automated clients.&lt;/p>
&lt;p>There are two main options here:&lt;/p>
&lt;ol>
&lt;li>Obtaining a server certificate and private key from your organization CA&lt;/li>
&lt;li>Generating a server certificate and private key from the self-signed CA&lt;/li>
&lt;/ol>
&lt;h3 id="obtaining-a-server-certificate-and-private-key-from-your-organization-ca">Obtaining a server certificate and private key from your organization CA&lt;/h3>
&lt;p>If your organization has a CA certificate, you should request a server certificate for use with Gate.&lt;/p>
&lt;p>Because the X509 API is exposed directly to your automation endpoints, it may be helpful to request a certificate with a CN that matches a DNS name that resolves to your load balancer. For example, if you can point &lt;code>api.spinnaker.domain.com&lt;/code> at your load balancer, you may want to request a certificate that has &lt;code>api.spinnaker.domain.com&lt;/code> as its CN.&lt;/p>
&lt;p>Alternatively you can configure your clients to skip server certificate validation (this is usually the &lt;code>-k&lt;/code> flag for &lt;code>curl&lt;/code>).&lt;/p>
&lt;p>This should result in the following files:&lt;/p>
&lt;ul>
&lt;li>&lt;code>gate.key&lt;/code>: a &lt;code>pem&lt;/code>-formatted private key, which will have a pass phrase.&lt;/li>
&lt;li>&lt;code>gate.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted x509 certificate, which matches the private key and was signed by your CA.&lt;/li>
&lt;/ul>
&lt;h3 id="generating-a-server-certificate-and-private-key-from-the-self-signed-ca">Generating a server certificate and private key from the self-signed CA&lt;/h3>
&lt;p>If you want to generate your own certificates (for example, from the self-signed CA certificate created above), you can follow these steps:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Create a server key for Gate. Keep this file safe!&lt;/p>
&lt;p>This will prompt for a pass phrase to encrypt the key.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This will be the passphrase used to encrypt the Gate private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">GATE_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_GATE_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl genrsa &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -des3 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out gate.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GATE_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Generate a certificate signing request (CSR) for Gate. Ideally, specify
Gate&amp;rsquo;s eventual fully-qualified domain name (FQDN) as the Common Name (CN).&lt;/p>
&lt;p>This will prompt for the pass phrase for &lt;code>gate.key&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the passphrase used to encrypt the Gate private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">GATE_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_GATE_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -new &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -key gate.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out gate.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GATE_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Use the CA to sign the server&amp;rsquo;s request and create the Gate server certificate in &lt;code>pem&lt;/code> format. If using an external CA, they do this for you.&lt;/p>
&lt;p>This prompts for the passphrase used to encrypt &lt;code>ca.key&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the passphrase used to encrypt the self-signed CA private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_CA_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl x509 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -sha256 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -days &lt;span style="color:#bd93f9">365&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -in gate.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CA ca.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAkey ca.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAcreateserial &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out gate.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note: if you omit the &lt;code>-sha256&lt;/code> argument, &lt;code>openssl x509&lt;/code> creates a certificate that&amp;rsquo;s not valid to use with Gate. When you import the invalid certificate into a Java KeyStore (JKS), you see &lt;code>Warning: &amp;lt;gate&amp;gt; uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.&lt;/code> Then Gate throws an &lt;code>Invalid keystore&lt;/code> format when importing the JKS.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>You should end up with these two files:&lt;/p>
&lt;ul>
&lt;li>&lt;code>gate.key&lt;/code>: a &lt;code>pem&lt;/code>-formatted private key, which will have a pass phrase&lt;/li>
&lt;li>&lt;code>gate.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted x509 certificate, which matches the private key and was signed by your CA&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="checkpoint">Checkpoint&lt;/h2>
&lt;p>At this point, you should have these files:
* &lt;code>deck.key&lt;/code> (with a distinct passphrase)
* &lt;code>deck.crt&lt;/code>
* &lt;code>gate.key&lt;/code> (with a distinct passphrase)
* &lt;code>gate.crt&lt;/code>
* &lt;code>ca.crt&lt;/code>&lt;/p>
&lt;p>Also, if you are using a self-signed CA, you will also have these files:
* &lt;code>ca.key&lt;/code> (with a distinct passphrase)
* &lt;code>ca.srl&lt;/code> (automatically generated, used to keep track of certificates generated by a given CA)&lt;/p>
&lt;p>We will use all of these below.&lt;/p>
&lt;h2 id="create-a-jks">Create a JKS&lt;/h2>
&lt;p>Gate expects all certificates in JKS (Java KeyStore) format, so we have to do some conversion and combination. Specifically, we will generate a JKS that has these two items in it:&lt;/p>
&lt;ul>
&lt;li>An entry containing the &lt;strong>Gate&lt;/strong> private key and public certificate&lt;/li>
&lt;li>An entry containing the &lt;strong>CA&lt;/strong> public certificate&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>
&lt;p>Convert the &lt;code>pem&lt;/code> format Gate server certificate into a PKCS12 (&lt;code>p12&lt;/code>) file,
which is importable into a Java Keystore (JKS).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># GATE_KEY_PASSWORD should be the passphrase you used to encrypt `gate.key`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">GATE_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_GATE_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># GATE_EXPORT_PASSWORD can be a new passphrase that will be used to encrypted `gate.p12`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">GATE_EXPORT_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_GATE_P12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl pkcs12 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -export &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -clcerts &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -in gate.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -inkey gate.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out gate.p12 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -name gate &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GATE_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -password pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GATE_EXPORT_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This creates a p12 keystore file with your certificate imported under the alias &amp;ldquo;gate&amp;rdquo;.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Create a new Java Keystore (JKS) containing your &lt;code>p12&lt;/code>-formatted Gate server certificate.&lt;/p>
&lt;p>Because Gate assumes that the keystore password and the password for the key
in the keystore are the same, we must provide both via the command line.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># GATE_EXPORT_PASSWORD should be the passphrase that was used to encrypted `gate.p12`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">GATE_EXPORT_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_GATE_P12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># JKS_PASSWORD can be a new password that will be used to encrypt `gate.jks`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_JKS_PASSWORD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keytool -importkeystore &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -srckeystore gate.p12 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -srcstoretype pkcs12 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -srcalias gate &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -destkeystore gate.jks &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -destalias gate &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -deststoretype pkcs12 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -deststorepass &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -destkeypass &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -srcstorepass &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GATE_EXPORT_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Import the CA certificate into the Java Keystore.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># JKS_PASSWORD should be the password that was used to encrypt `gate.jks`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_JKS_PASSWORD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keytool -importcert &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -keystore gate.jks &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -alias ca &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -file ca.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -storepass &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -noprompt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Verify the Java Keystore contains the correct contents.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># JKS_PASSWORD should be the password that was used to encrypt `gate.jks`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_JKS_PASSWORD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keytool &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -list &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -keystore gate.jks &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -storepass &lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">JKS_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It should contain two entries:&lt;/p>
&lt;ul>
&lt;li>&lt;code>gate&lt;/code> as a &lt;code>PrivateKeyEntry&lt;/code>&lt;/li>
&lt;li>&lt;code>ca&lt;/code> as a &lt;code>trustedCertEntry&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="back-up-your-spinnaker-configuration">Back Up Your Spinnaker Configuration&lt;/h2>
&lt;p>Backup all &lt;code>SpinnakerService&lt;/code> related files.&lt;/p>
&lt;h2 id="enable-ssl-for-the-ui">Enable SSL for the UI&lt;/h2>
&lt;p>Next, configure Spinnaker&amp;rsquo;s Deck service to use the Deck certificate and private key that you generated.&lt;/p>
&lt;blockquote>
&lt;p>The Kubernetes secret engine does not work for encrypting secrets for the UI.&lt;/p>
&lt;/blockquote>
&lt;p>Add the following snippet to the &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">uiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sslCertificateFile&lt;/span>: encryptedFile:k8s!n:spin-deck-secrets!k:deck.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sslCertificateKeyFile&lt;/span>: encryptedFile:k8s!n:spin-deck-secrets!k:deck.key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">sslCertificatePassphrase&lt;/span>: abc &lt;span style="color:#6272a4"># Your passphrase&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create a new Kubernetes secret containing the files. The following example assumes that Spinnaker is installed in the &lt;code>spinnaker&lt;/code> namespace, and you are in the folder where &lt;code>deck.crt&lt;/code> and &lt;code>deck.key&lt;/code> are located:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n spinnaker create secret generic spin-deck-secrets --from-file&lt;span style="color:#ff79c6">=&lt;/span>deck.crt --from-file&lt;span style="color:#ff79c6">=&lt;/span>deck.key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Depending on how your load balancer is configured (if you&amp;rsquo;re using an Ingress vs. a Service), you may have to change your service and/or ingress configuration. This is discussed below, in &lt;strong>Update Load Balancers and URLs&lt;/strong>&lt;/p>
&lt;h2 id="enable-ssl-for-the-api">Enable SSL for the API&lt;/h2>
&lt;p>Next, we will configure Spinnaker&amp;rsquo;s Gate service to use the JKS that we&amp;rsquo;ve generated.&lt;/p>
&lt;p>Add the following snippet to the &lt;code>SpinnakerService&lt;/code> manifest:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/{{ site.data.versions.perator-extended-crd-version }}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyAlias&lt;/span>: gate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyStore&lt;/span>: encryptedFile:k8s!n:spin-gate-secrets!k:gate.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyStoreType&lt;/span>: jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">keyStorePassword&lt;/span>: abc &lt;span style="color:#6272a4"># The password to unlock your keystore. Due to a limitation in Tomcat, this must match your key&amp;#39;s password in the keystore.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trustStore&lt;/span>: encryptedFile:k8s!n:spin-gate-secrets!k:gate.jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trustStoreType&lt;/span>: jks
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">trustStorePassword&lt;/span>: abc &lt;span style="color:#6272a4"># The password to unlock your truststore.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">clientAuth&lt;/span>: WANT &lt;span style="color:#6272a4"># Declare &amp;#39;WANT&amp;#39; when client auth is wanted but not mandatory, or &amp;#39;NEED&amp;#39;, when client auth is mandatory.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create a new Kubernetes secret having the above files. Here we assume that Spinnaker is installed in the &lt;code>spinnaker&lt;/code> namespace, and you are in the folder where &lt;code>gate.jks&lt;/code> is located:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n spinnaker create secret generic spin-gate-secrets --from-file&lt;span style="color:#ff79c6">=&lt;/span>gate.jks
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="update-load-balancers-and-urls">Update load balancers and URLs&lt;/h2>
&lt;p>When you apply the above changes, Gate and Deck will change in the following ways:&lt;/p>
&lt;ul>
&lt;li>Deck will continue to use port 9000, but it will be an HTTPS port instead of an HTTP port&lt;/li>
&lt;li>Gate will continue to use port 8084, but it will be an HTTPS port instead of an HTTP port&lt;/li>
&lt;/ul>
&lt;p>Depending on your load balancer and infrastructure configuration, this will likely necessitate one of the following changes:&lt;/p>
&lt;ul>
&lt;li>If you have a load balancer (such as an Ingress) in front of your Gate/Deck, you&amp;rsquo;ll likely need to change the way that Ingress communicates with Deck/Gate.&lt;/li>
&lt;li>If you have no load balancer in front of your Gate/Deck and are instead using a basic Kubernetes Service, you&amp;rsquo;ll likely need to change the base URL overrides for Deck and Gate&lt;/li>
&lt;/ul>
&lt;h3 id="changing-ingress">Changing ingress&lt;/h3>
&lt;p>If you are using an Ingress in front of Deck and Gate, the Ingress is likely configured to communicate via HTTP to your backend services. You&amp;rsquo;ll need to change this to communicate via HTTPS.&lt;/p>
&lt;p>The mechanism to achieve this will depend on what type of Ingress you are using. Here are two of the most common:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>If you are using an NGINX Ingress Controller, you will need to add these annotations to the &lt;code>Ingress&lt;/code> resource that is set up for Deck and gate:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">nginx.ingress.kubernetes.io/backend-protocol&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;HTTPS&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>If you are using the Amazon AWS ALB Ingress Controller, you will need to add these annotations to the &lt;code>Ingress&lt;/code> resource that is set up for Deck and gate:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">alb.ingress.kubernetes.io/backend-protocol&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;HTTPS&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">alb.ingress.kubernetes.io/healthcheck-protocol&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;HTTPS&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="changing-url-overrides">Changing URL overrides&lt;/h3>
&lt;p>If you are instead using a Layer 4 (TCP) load balancer (such as a &lt;code>Service&lt;/code> configured as a &lt;code>LoadBalancer&lt;/code> in EKS), or directly exposing your Kubernetes &lt;code>Service&lt;/code> objects using a &lt;code>NodePort&lt;/code> configuration, then you&amp;rsquo;ll need to change the base URL overrides.&lt;/p>
&lt;p>In the &lt;code>SpinnakerService&lt;/code> manifest you need to change the &lt;code>overrideBaseUrl&lt;/code> settings of Deck and Gate in the following way:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">overrideBaseUrl&lt;/span>: https://spinnaker.domain.com/api/v1 &lt;span style="color:#6272a4"># URL to access Gate, using HTTPS scheme&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">uiSecurity&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">overrideBaseUrl&lt;/span>: https://spinnaker.domain.com &lt;span style="color:#6272a4"># URL to access Deck, using HTTPS scheme&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Although Spinnaker also supports using a different DNS name, Armory recommends that you use the same DNS but different paths for Deck and Gate. Tasks such as Cross-Origin Resource Sharing (CORS) between your Gate and Deck endpoints and securing Gate and Deck are much easier when both services use the same DNS name.&lt;/p>
&lt;h2 id="apply-ssl-changes">Apply SSL Changes&lt;/h2>
&lt;p>Before enabling the API endpoint, we should apply the changes that we&amp;rsquo;ve made so far and make sure everything continues to work.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>
&lt;p>Apply your Ingress / Service changes, as indicated abvoe in the &lt;strong>Changing Ingress&lt;/strong> section.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Verify that you&amp;rsquo;re still able to access Spinnaker. You may have to switch existing URLs from &lt;code>http&lt;/code> to &lt;code>https&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Verify that you can still see Spinnaker applications and pipelines as before.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If you have any issues, perform various troubleshooting steps (such as those related to HTTPS in our &lt;a href="https://kb.armory.io/s/category-knowledge?categ=Troubleshooting">KB&lt;/a>), or restore your prior backup:&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Apply the backed up manifests files with &lt;code>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f ...&lt;/code>&lt;/p>
&lt;h2 id="gate-local">Gate-local&lt;/h2>
&lt;p>Once you&amp;rsquo;ve verified that your existing Gate and Deck endpoints continue to work as expected, we can enable the API endpoint. This requires the following steps:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Enable x509 Authentication&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">authn&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">x509&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Configure Gate to use a second port for the x509 API port.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">profiles&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">gate&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">apiPort&lt;/span>: &lt;span style="color:#bd93f9">8085&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Apply your changes&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Gate will now have a second API port set up listening on port 8085, which will expect an x509 client certificate from all clients trying to communicate with it. We have to expose this port externally.&lt;/p>
&lt;h2 id="update-load-balancers-and-urls-1">Update load balancers and URLs&lt;/h2>
&lt;p>You must expose port 8085 on your Gate containers externally, and you should &lt;strong>not&lt;/strong> terminate TLS in front of them. Depending on how your Kubernetes cluster lives, you may be able to use a &lt;code>LoadBalancer&lt;/code> or &lt;code>NodePort&lt;/code> Service. Alternatively, if your Ingress Controller is configured to support TLS pass-through, you can use that.&lt;/p>
&lt;p>Operator automatically exposes Gate&amp;rsquo;s API port.&lt;/p>
&lt;p>For example, with the LoadBalancer configuration in EKS, you will get an ELB endpoint (get this with &lt;code>kubectl -n NAMESPACE get svc -owide&lt;/code>). With the NodePort configuration, you can use any instance in your cluster with the generated NodePort port.&lt;/p>
&lt;p>You can verify that the client certificate is set up properly by &lt;code>curl&lt;/code>ing the endpoint with the &lt;code>-v&lt;/code> and &lt;code>-k&lt;/code> (verbose, no validation) flags. You should get an alert for bad certificate, since the endpoint is expecting a client certificate and you are not providing one:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl https://&amp;lt;endpoint&amp;gt;:8085 -v -k
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl https://abcd-123456789.us-west-2.elb.amazonaws.com:8085 -v -k
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* Rebuilt URL to: https://abcd-123456789.us-west-2.elb.amazonaws.com:8085/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* Trying 35.0.0.1...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TCP_NODELAY &lt;span style="color:#8be9fd;font-style:italic">set&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* Connected to abcd-123456789.us-west-2.elb.amazonaws.com &lt;span style="color:#ff79c6">(&lt;/span>35.0.0.1&lt;span style="color:#ff79c6">)&lt;/span> port &lt;span style="color:#bd93f9">8085&lt;/span> &lt;span style="color:#ff79c6">(&lt;/span>&lt;span style="color:#6272a4">#0)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* ALPN, offering h2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* ALPN, offering http/1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* successfully &lt;span style="color:#8be9fd;font-style:italic">set&lt;/span> certificate verify locations:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* CAfile: /etc/ssl/cert.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CApath: none
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>OUT&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Client hello &lt;span style="color:#ff79c6">(&lt;/span>1&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>IN&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Server hello &lt;span style="color:#ff79c6">(&lt;/span>2&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>IN&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Certificate &lt;span style="color:#ff79c6">(&lt;/span>11&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>IN&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Server key exchange &lt;span style="color:#ff79c6">(&lt;/span>12&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>IN&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Request CERT &lt;span style="color:#ff79c6">(&lt;/span>13&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>IN&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Server finished &lt;span style="color:#ff79c6">(&lt;/span>14&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>OUT&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Certificate &lt;span style="color:#ff79c6">(&lt;/span>11&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>OUT&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Client key exchange &lt;span style="color:#ff79c6">(&lt;/span>16&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>OUT&lt;span style="color:#ff79c6">)&lt;/span>, TLS change cipher, Client hello &lt;span style="color:#ff79c6">(&lt;/span>1&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>OUT&lt;span style="color:#ff79c6">)&lt;/span>, TLS handshake, Finished &lt;span style="color:#ff79c6">(&lt;/span>20&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* TLSv1.2 &lt;span style="color:#ff79c6">(&lt;/span>IN&lt;span style="color:#ff79c6">)&lt;/span>, TLS alert, Server hello &lt;span style="color:#ff79c6">(&lt;/span>2&lt;span style="color:#ff79c6">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* error:1401E412:SSL routines:CONNECT_CR_FINISHED:sslv3 alert bad certificate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* stopped the pause stream!
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* Closing connection &lt;span style="color:#bd93f9">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl: &lt;span style="color:#ff79c6">(&lt;/span>35&lt;span style="color:#ff79c6">)&lt;/span> error:1401E412:SSL routines:CONNECT_CR_FINISHED:sslv3 alert bad certificate
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="signing-client-certificates-using-the-self-signed-ca">Signing client certificates using the self-signed CA&lt;/h2>
&lt;p>If you created a self-signed CA, you can use that CA to sign certificates for your API clients to use.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Create the client key. Keep this file safe!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This will be the passphrase used to encrypt the client private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_CLIENT_PASSPHRASE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl genrsa &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -des3 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out client.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Generate a certificate signing request for the client. Ensure the &lt;code>Common Name&lt;/code> is set to a non-empty value.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the same passphrase used to encrypt the client private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_CLIENT_PASSPHRASE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -new &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -key client.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out client.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Use the CA to sign the client&amp;rsquo;s request.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the passphrase used to encrypt the self-signed CA private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_CA_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl x509 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -days &lt;span style="color:#bd93f9">365&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -in client.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CA ca.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAkey ca.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAcreateserial &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out client.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>You should end up with these two files:&lt;/p>
&lt;ul>
&lt;li>&lt;code>client.key&lt;/code>: a &lt;code>pem&lt;/code>-formatted private key, which will have a pass phrase&lt;/li>
&lt;li>&lt;code>client.crt&lt;/code>: a &lt;code>pem&lt;/code>-formatted x509 certificate, which matches the private key and was signed by your CA&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="connecting-to-the-api-with-the-client-certificate">Connecting to the API with the client certificate&lt;/h2>
&lt;p>Now that you have a client certificate (with key), you can use it to connect to the Spinnaker API. For example, to get a list of Spinnaker applications from Gate:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl https://abcd-123456789.us-west-2.elb.amazonaws.com:8085//applications &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -k &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --cert client.crt:SOME_CLIENT_PASSPHRASE&lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --key client.key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[{&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;accounts&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;spinnaker&amp;#34;&lt;/span>,&lt;span style="color:#f1fa8c">&amp;#34;name&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;ingress&amp;#34;&lt;/span>&lt;span style="color:#ff79c6">}&lt;/span>,&lt;span style="color:#ff79c6">{&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;accounts&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;spinnaker&amp;#34;&lt;/span>,&lt;span style="color:#f1fa8c">&amp;#34;name&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;ldap&amp;#34;&lt;/span>&lt;span style="color:#ff79c6">}&lt;/span>,&lt;span style="color:#ff79c6">{&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;accounts&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;spinnaker&amp;#34;&lt;/span>,&lt;span style="color:#f1fa8c">&amp;#34;name&amp;#34;&lt;/span>:&lt;span style="color:#f1fa8c">&amp;#34;spin&amp;#34;&lt;/span>&lt;span style="color:#ff79c6">}]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="using-authorization-with-spinnaker-and-other-configurations">Using Authorization with Spinnaker, and other Configurations&lt;/h2>
&lt;p>If your Spinnaker is configured with Authorization (based on groups), it can be helpful to encode groups into the client Certificate that will allow the API client access to things that are restricted to specific groups. This is achieved by doing these two things:&lt;/p>
&lt;ul>
&lt;li>Configuring Gate to look at a specific OID in the client certificate for groups&lt;/li>
&lt;li>Adding the groups at that specific OID in the client certificate&lt;/li>
&lt;/ul>
&lt;h3 id="configuring-gate-to-use-a-specific-oid-for-groups">Configuring Gate to use a specific OID for groups&lt;/h3>
&lt;p>The OID &lt;code>1.2.840.10070.8.1&lt;/code> is used to identify roles for a given user, so it is perfect for identifying the groups that a given client certificate will have access to.&lt;/p>
&lt;p>You can configure Gate to look for a list of endline-delimited groups in the &lt;code>1.2.840.10070.8.1&lt;/code> OID:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">authn&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">x509&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">roleOid&lt;/span>: &lt;span style="color:#bd93f9">1.2.840.10070.8.1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="adding-groups-and-signing-certificates-with-the-oid-extensions">Adding groups and signing certificates with the OID extensions&lt;/h3>
&lt;p>In order to allow a client certificate access to specific groups, when you&amp;rsquo;re generating the CSR and the certificate, you can specify custom fields in OpenSSL by providing them via an OpenSSL configuration file. For example, to add these two groups:&lt;/p>
&lt;ul>
&lt;li>spinnaker-example0&lt;/li>
&lt;li>spinnaker-example1&lt;/li>
&lt;/ul>
&lt;p>To a client certificate, construct a string with the groups delimited by &lt;code>\n&lt;/code>, like this:
&lt;code>spinnaker-example0\nspinnaker-example1&lt;/code>.&lt;/p>
&lt;p>Then, add that to a configuration file that looks like this (replacing &lt;code>GROUP_STRING&lt;/code> with your group string)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># group.conf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span> req &lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">distinguished_name&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> req_distinguished_name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">attributes&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> req_attributes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">req_extensions&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> v3_req
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span> req_distinguished_name &lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">countryName&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> Country Name &lt;span style="color:#ff79c6">(&lt;/span>&lt;span style="color:#bd93f9">2&lt;/span> letter code&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">countryName_min&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> &lt;span style="color:#bd93f9">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">countryName_max&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> &lt;span style="color:#bd93f9">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">stateOrProvinceName&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> State or Province Name &lt;span style="color:#ff79c6">(&lt;/span>full name&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">localityName&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> Locality Name &lt;span style="color:#ff79c6">(&lt;/span>eg, city&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0.organizationName &lt;span style="color:#ff79c6">=&lt;/span> Organization Name &lt;span style="color:#ff79c6">(&lt;/span>eg, company&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">organizationalUnitName&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> Organizational Unit Name &lt;span style="color:#ff79c6">(&lt;/span>eg, section&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">commonName&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> Common Name &lt;span style="color:#ff79c6">(&lt;/span>eg, fully qualified host name&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">commonName_max&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> &lt;span style="color:#bd93f9">64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">emailAddress&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> Email Address
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">emailAddress_max&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> &lt;span style="color:#bd93f9">64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span> req_attributes &lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">challengePassword&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> A challenge password
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">challengePassword_min&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> &lt;span style="color:#bd93f9">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">challengePassword_max&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> &lt;span style="color:#bd93f9">20&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">[&lt;/span> v3_req &lt;span style="color:#ff79c6">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">keyUsage&lt;/span> &lt;span style="color:#ff79c6">=&lt;/span> nonRepudiation, digitalSignature, keyEncipherment
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1.2.840.10070.8.1 &lt;span style="color:#ff79c6">=&lt;/span> ASN1:UTF8String:GROUP_STRING
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here&amp;rsquo;s an example of how to use this:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Create the configuration file&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>tee group.conf &lt;span style="color:#f1fa8c">&amp;lt;&amp;lt;-&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">[ req ]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">distinguished_name = req_distinguished_name
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">attributes = req_attributes
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">req_extensions = v3_req
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">[ req_distinguished_name ]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">countryName = Country Name (2 letter code)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">countryName_min = 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">countryName_max = 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">stateOrProvinceName = State or Province Name (full name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">localityName = Locality Name (eg, city)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">0.organizationName = Organization Name (eg, company)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">organizationalUnitName = Organizational Unit Name (eg, section)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">commonName = Common Name (eg, fully qualified host name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">commonName_max = 64
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">emailAddress = Email Address
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">emailAddress_max = 64
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">[ req_attributes ]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">challengePassword = A challenge password
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">challengePassword_min = 4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">challengePassword_max = 20
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">[ v3_req ]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">keyUsage = nonRepudiation, digitalSignature, keyEncipherment
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">1.2.840.10070.8.1 = ASN1:UTF8String:spinnaker-example0\nspinnaker-example1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Create the client key. Keep this file safe!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This will be the passphrase used to encrypt the client private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_CLIENT_PASSPHRASE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl genrsa &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -des3 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out client.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Specify the configuration file when you generate the CSR with the &lt;code>-config group.conf&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the same passphrase used to encrypt the client private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_CLIENT_PASSPHRASE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -new &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -key client.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out client.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CLIENT_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -config group.conf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Specify the configuration file when you use the CA to sign the certificate with the &lt;code>-extensions v3_req&lt;/code> and &lt;code>-extfile group.conf&lt;/code> flags:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># This should be the passphrase used to encrypt the self-signed CA private key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>SOME_PASSWORD_FOR_CA_KEY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl x509 &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -days &lt;span style="color:#bd93f9">365&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -in client.csr &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CA ca.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAkey ca.key &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -CAcreateserial &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out client.crt &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_KEY_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -extensions v3_req &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -extfile group.conf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Now, when you use the generated certificate and key, your API client will be able to access Spinnaker items that are restricted to those groups.&lt;/p>
&lt;h3 id="configuring-spinnaker-to-parse-out-usernames-from-client-certificates">Configuring Spinnaker to parse out usernames from client certificate(s)&lt;/h3>
&lt;p>When looking at audit logs, it can be helpful to differentiate different API clients. One way to achieve this is to parse out a &amp;ldquo;username&amp;rdquo; from the client for each API client certificate. This is achieved by configuring Spinnaker to use regex to pull out a subject from the certificate. This is set up with the &lt;code>subject principal regex&lt;/code> field, which is configured like this:&lt;/p>
&lt;p>&lt;strong>Operator&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">security&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">authn&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">x509&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">subjectPrincipalRegex&lt;/span>: DESIRED_REGEX &lt;span style="color:#6272a4"># For example, if you want to use the &amp;#34;Email Address&amp;#34; field from the certificate, the regex would be: EMAILADDRESS=(.*?)(?:,|$)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="verify-the-x509-certificate">Verify the x509 certificate&lt;/h3>
&lt;p>Make a call to &lt;code>https://${GATE_FQDN}/auth/user&lt;/code> to verify the setup is correct. The call should return the certificate&amp;rsquo;s Spinnaker login and authorization information. For example, here&amp;rsquo;s a call using curl:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl --cacert ca.crt --key client.key --cert client.crt https://&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GATE_FQDN&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>/auth/user
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Continuous-Deployment: Generate Certificates for Spinnaker</title><link>/continuous-deployment/armory-admin/generating-certificates/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/generating-certificates/</guid><description>
&lt;h2 id="before-you-begin">Before you begin&lt;/h2>
&lt;ul>
&lt;li>Make sure you are using the same version of Java that Armory Continuous Deployment is using.&lt;/li>
&lt;li>You need a recent version of OpenSSL.&lt;/li>
&lt;/ul>
&lt;h2 id="generating-self-signed-certificate-authority">Generating self-signed certificate authority&lt;/h2>
&lt;p>Generate a key for our certificate authority:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>openssl genrsa -aes256 -passout pass:TRUSTSTORE_PASS -out ca.key &lt;span style="color:#bd93f9">2048&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Replace &lt;code>TRUSTSTORE_PASS&lt;/code> with your own CA password.&lt;/p>
&lt;p>&lt;strong>Important:&lt;/strong> Keep &lt;code>ca.key&lt;/code> secure and do not distribute it.&lt;/p>
&lt;p>Next, generate the certificate of the CA:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>openssl req -x509 -new -nodes -key ca.key -sha256 -days &lt;span style="color:#bd93f9">3650&lt;/span> -out ca.pem -passin pass:TRUSTSTORE_PASS -subj /C&lt;span style="color:#ff79c6">=&lt;/span>US/ST&lt;span style="color:#ff79c6">=&lt;/span>California/O&lt;span style="color:#ff79c6">=&lt;/span>Acme Corp/OU&lt;span style="color:#ff79c6">=&lt;/span>Devops/CN&lt;span style="color:#ff79c6">=&lt;/span>mydomain.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Replace the values of the &lt;code>subj&lt;/code> parameter with your own. Only the &lt;code>CN&lt;/code> part is required and doesn&amp;rsquo;t need to match a real domain.&lt;/p>
&lt;h2 id="generating-a-pkcs12-truststore-java">Generating a PKCS12 truststore (Java)&lt;/h2>
&lt;p>Import the &lt;code>ca.pem&lt;/code> file you generated into a Java truststore:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>keytool -importcert -storetype PKCS12 -keystore services/ca.p12 -storepass TRUSTSTORE_PASS -alias ca -file ca.pem -noprompt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="generating-a-keystore-for-a-java-server">Generating a keystore for a Java server&lt;/h2>
&lt;p>The &lt;code>CN&lt;/code> attribute must match the hostname of the service. It will generally be &lt;code>spin-[service].[namespace]&lt;/code> or &lt;code>spin-[service]&lt;/code>, for example &lt;code>spin-clouddriver.spinnaker&lt;/code>.&lt;/p>
&lt;p>Generate the keystore with the following commands:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>openssl genrsa -aes256 -passout pass:KEY_PASSWORD -out svc.key &lt;span style="color:#bd93f9">2048&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req -new -key svc.key -out svc.csr -subj /C&lt;span style="color:#ff79c6">=&lt;/span>US/CN&lt;span style="color:#ff79c6">=&lt;/span>spin-svc.spinnaker -passin pass:KEY_PASSWORD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl x509 -req -in svc.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out svc.crt -days &lt;span style="color:#bd93f9">3649&lt;/span> -sha256 -passin pass:TRUSTSTORE_PASS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl pkcs12 -export -out svc.p12 -inkey svc.key -in svc.crt -passout pass:KEY_PASSWORD -passin pass:KEY_PASSWORD
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="alternate-names">Alternate names&lt;/h3>
&lt;p>If you want the Spinnaker service to support alternate names, replace the &lt;code>openssl pkcs12&lt;/code> command in the previous section with:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>openssl x509 -req -sha256 -in svc.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out svc.crt -days &lt;span style="color:#bd93f9">3650&lt;/span> -extfile svc-cert.ext -passin pass:TRUSTSTORE_PASS
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>svc-cert.ext&lt;/code> referenced in the command should contain the following (example for Clouddriver):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>authorityKeyIdentifier=keyid,issuer
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>basicConstraints=CA:FALSE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>subjectAltName = @alt_names
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[alt_names]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>DNS.1 = spin-clouddriver.spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>DNS.2 = spin-clouddriver
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Note&lt;/strong>: If you are setting up mTLS, you can use the same command (or the same file) for client-side certificates.&lt;/p>
&lt;h2 id="generating-keys-and-certificates-golang">Generating keys and certificates (Golang)&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>openssl genrsa -aes256 -passout pass:KEY_PASSWORD -out svc.key &lt;span style="color:#bd93f9">2048&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req -new -key svc.key -out svc.csr -subj /C&lt;span style="color:#ff79c6">=&lt;/span>US/CN&lt;span style="color:#ff79c6">=&lt;/span>spin-svc.spinnaker -passin pass:KEY_PASSWORD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl x509 -req -in svc.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out svc.crt -days &lt;span style="color:#bd93f9">3650&lt;/span> -sha256 -passin pass:TRUSTSTORE_PASS
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="putting-it-together-tls">Putting it together (TLS)&lt;/h2>
&lt;p>The following script generates these files in the &lt;code>services&lt;/code> directory:&lt;/p>
&lt;ul>
&lt;li>Self-signed CA (&lt;code>ca.pem&lt;/code>) and its PKCS12 truststore (&lt;code>ca.p12&lt;/code>)&lt;/li>
&lt;li>Keystore files for each Java service (&lt;code>clouddriver.p12&lt;/code>, &amp;hellip;)&lt;/li>
&lt;li>Certificate and key files for each Golang services (&lt;code>terraformer.crt&lt;/code> and &lt;code>terraformer.key&lt;/code>, &amp;hellip;)&lt;/li>
&lt;li>a &lt;code>tls-passwords&lt;/code> file containing all the passwords. You can store as-is in a bucket.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">#!/bin/bash -e
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># You can change it to a different method&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>newPassword&lt;span style="color:#ff79c6">()&lt;/span> &lt;span style="color:#ff79c6">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#ff79c6">$(&lt;/span>openssl rand -base64 32&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># Namespace where you&amp;#39;re installing Spinnaker. Used for the hostname.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;spinnaker&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">CA_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;password&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">TRUSTSTORE_PASSWORD&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>newPassword&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">JAVA_SVCS&lt;/span>&lt;span style="color:#ff79c6">=(&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;clouddriver&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;orca&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;echo&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;fiat&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;igor&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;rosco&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;front50&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;kayenta&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;gate&amp;#34;&lt;/span>&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6272a4"># JAVA_SVCS=(&amp;#34;clouddriver-rw&amp;#34; &amp;#34;clouddriver-caching&amp;#34; &amp;#34;clouddriver-ro&amp;#34; &amp;#34;clouddriver-ro-deck&amp;#34; &amp;#34;orca&amp;#34; &amp;#34;echo-scheduler&amp;#34; &amp;#34;echo-worker&amp;#34; &amp;#34;fiat&amp;#34; &amp;#34;igor&amp;#34; &amp;#34;rosco&amp;#34; &amp;#34;front50&amp;#34; &amp;#34;kayenta&amp;#34; &amp;#34;gate&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">GOLANG_SVCS&lt;/span>&lt;span style="color:#ff79c6">=(&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;dinghy&amp;#34;&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;terraformer&amp;#34;&lt;/span>&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;Cleaning up...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm -rf services/*
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mkdir -p services/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;Generating CA key...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl genrsa -aes256 -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -out services/ca.key &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;Generate self signed root certificate&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssl req -x509 -new -nodes -key services/ca.key -sha256 -days &lt;span style="color:#bd93f9">3650&lt;/span> -out services/ca.pem -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -subj /C&lt;span style="color:#ff79c6">=&lt;/span>US/CN&lt;span style="color:#ff79c6">=&lt;/span>Test
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;Generate trust store as PKCS12&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keytool -importcert -storetype PKCS12 -keystore services/ca.p12 -storepass &lt;span style="color:#8be9fd;font-style:italic">$TRUSTSTORE_PASSWORD&lt;/span> -alias ca -file services/ca.pem -noprompt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;truststore: &lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">TRUSTSTORE_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;&lt;/span> &amp;gt; services/tls-passwords
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">for&lt;/span> i in &lt;span style="color:#f1fa8c">${&lt;/span>!JAVA_SVCS[@]&lt;span style="color:#f1fa8c">}&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">JAVA_SVCS&lt;/span>[&lt;span style="color:#8be9fd;font-style:italic">$i&lt;/span>]&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>newPassword&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;Generating &lt;/span>&lt;span style="color:#8be9fd;font-style:italic">$svc&lt;/span>&lt;span style="color:#f1fa8c"> key and certificate...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl genrsa -aes256 -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.key &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl req -new -key services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.key -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.csr -subj /C&lt;span style="color:#ff79c6">=&lt;/span>US/CN&lt;span style="color:#ff79c6">=&lt;/span>spin-&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cat &lt;span style="color:#f1fa8c">&amp;lt;&amp;lt;EOF&amp;gt;services/${svc}.ext
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">authorityKeyIdentifier=keyid,issuer
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">basicConstraints=CA:FALSE
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">subjectAltName = @alt_names
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">[alt_names]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">DNS.1 = spin-${svc}.${NAMESPACE}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">DNS.2 = spin-${svc}.${NAMESPACE}.svc.cluster.local
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl x509 -req -in services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.csr -CA services/ca.pem -CAkey services/ca.key -CAcreateserial -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.crt -days &lt;span style="color:#bd93f9">3649&lt;/span> -sha256 -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -extfile services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.ext
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl pkcs12 -export -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.p12 -inkey services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.key -in services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.crt -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;&lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>&lt;span style="color:#f1fa8c">: &lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;&lt;/span> &amp;gt;&amp;gt; services/tls-passwords
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">done&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">for&lt;/span> i in &lt;span style="color:#f1fa8c">${&lt;/span>!GOLANG_SVCS[@]&lt;span style="color:#f1fa8c">}&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">GOLANG_SVCS&lt;/span>[&lt;span style="color:#8be9fd;font-style:italic">$i&lt;/span>]&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#ff79c6">=&lt;/span>&lt;span style="color:#ff79c6">$(&lt;/span>newPassword&lt;span style="color:#ff79c6">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;Generating &lt;/span>&lt;span style="color:#8be9fd;font-style:italic">$svc&lt;/span>&lt;span style="color:#f1fa8c"> key and certificate...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl genrsa -aes256 -passout pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.key &lt;span style="color:#bd93f9">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cat &lt;span style="color:#f1fa8c">&amp;lt;&amp;lt;EOF&amp;gt;services/${svc}.ext
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">authorityKeyIdentifier=keyid,issuer
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">basicConstraints=CA:FALSE
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">subjectAltName = @alt_names
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">[alt_names]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">DNS.1 = spin-${svc}.${NAMESPACE}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">DNS.2 = spin-${svc}.${NAMESPACE}.svc.cluster.local
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl req -new -key services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.key -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.csr -subj /C&lt;span style="color:#ff79c6">=&lt;/span>US/CN&lt;span style="color:#ff79c6">=&lt;/span>spin-&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">NAMESPACE&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> openssl x509 -req -in services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.csr -CA services/ca.pem -CAkey services/ca.key -CAcreateserial &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> -out services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.crt -days &lt;span style="color:#bd93f9">3650&lt;/span> -sha256 -passin pass:&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">CA_PASSWORD&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span> -extfile services/&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>.ext
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8be9fd;font-style:italic">echo&lt;/span> &lt;span style="color:#f1fa8c">&amp;#34;&lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">svc&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>&lt;span style="color:#f1fa8c">: &lt;/span>&lt;span style="color:#f1fa8c">${&lt;/span>&lt;span style="color:#8be9fd;font-style:italic">password&lt;/span>&lt;span style="color:#f1fa8c">}&lt;/span>&lt;span style="color:#f1fa8c">&amp;#34;&lt;/span> &amp;gt;&amp;gt; services/tls-passwords
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>
&lt;p>You may encounter the following error if the version of Java you are using to generate the certificates is not the same version that Armory Continuous Deployment is using:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>java.io.IOException: Integrity check failed: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Continuous-Deployment: Integrate ServiceNow with Spinnaker</title><link>/continuous-deployment/armory-admin/integrations-servicenow/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/integrations-servicenow/</guid><description>
&lt;h2 id="overview-of-servicenow">Overview of ServiceNow&lt;/h2>
&lt;p>&lt;a href="https://www.servicenow.com/">ServiceNow&lt;/a> provides several workflow solutions (ITSM, PPM, Security Response, ITOM, etc). Instead of defining a single use case for an integration that satisfies some use cases, this guide reviews the various building blocks available to create integrations through a generic webhook stage or a custom webhook stage.&lt;/p>
&lt;p>Consuming Webhooks in ServiceNow requires some configuration. You can read more about the process in the ServiceNow &lt;a href="https://community.servicenow.com/community?id=community_blog&amp;amp;sys_id=886d2a29dbd0dbc01dcaf3231f9619b0">docs&lt;/a>.&lt;/p>
&lt;h2 id="using-a-custom-webhook-stage-to-create-a-change-request-in-servicenow">Using a custom webhook stage to create a Change Request in ServiceNow&lt;/h2>
&lt;p>Potential uses for creating a change request in ServiceNow include:&lt;/p>
&lt;ul>
&lt;li>A deployment happens and a ticket needs to be filed in ServiceNow for record keeping&lt;/li>
&lt;li>A canary deployment is successful, and you need a change ticket to be created and approved before full deployment into production.&lt;/li>
&lt;/ul>
&lt;p>In ServiceNow, you need to create a Scripted Web Service. At a high level, this service performs the following actions:&lt;/p>
&lt;ul>
&lt;li>Receives the webhook from Spinnaker&lt;/li>
&lt;li>Processes the contents of the payload&lt;/li>
&lt;li>Creates a Change Request.&lt;/li>
&lt;/ul>
&lt;p>A very similar approach could be taken to create a different type of ticket.&lt;/p>
&lt;p>To create the Scripted Web Service, perform the following task:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Search for &lt;code>Scripted REST APIs&lt;/code> in the ServiceNow Navigator.&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-scripted-rest-apis.png"/>
&lt;/figure>
&lt;/li>
&lt;li>
&lt;p>Create a new Scripted Web Service and give it a descriptive name. For example, you can name it “SpinnakerWebhookListener”.&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-spinwebhooklistener.png"/>
&lt;/figure>
&lt;/li>
&lt;li>
&lt;p>Submit the information to create the service.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Create a Resource that contains the endpoint that Spinnaker and the script to create the ticket.&lt;/p>
&lt;p>You can create multiple Resources, each with its own specific URL and script to do something. In this example, the “SpinnakerWebhookListener” is the &lt;strong>Scripted REST API&lt;/strong> that handles all the various calls that Spinnaker makes to this specific ServiceNow Instance. You define Resources to handle each specific call. For example, you may want to create separate calls to create different type of tickets or perform different actions within ServiceNow.&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-create-resource.png"/>
&lt;/figure>
&lt;/li>
&lt;li>
&lt;p>Create a new resource and give it a meaningful name. The example below uses &lt;code>create-change-ticket&lt;/code>.&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-resource-changeticket.png"/>
&lt;/figure>
&lt;/li>
&lt;li>
&lt;p>Set the &lt;strong>HTTP method&lt;/strong> to &lt;strong>POST&lt;/strong>.&lt;/p>
&lt;p>If you are planning on having only one resource in the REST API, you can leave the &lt;strong>Relative Path&lt;/strong> as is.&lt;/p>
&lt;p>If you plan to create multiple Resources, set the relative path to be specific to this resource. This will be appended to the &lt;strong>API Path.&lt;/strong> The resulting path is appended to your ServiceNow instance address, and that is the URL Spinnaker uses.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: For testing the integration, you can opt to not require authentication.&lt;/p>
&lt;/blockquote>
&lt;/li>
&lt;li>
&lt;p>Optionally, provide the script. You can also provide one at a later time.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="example-script">Example script&lt;/h3>
&lt;p>The following is an example script you can use when configuring ServiceNow:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>(function process(/RESTAPIRequest/ request, /RESTAPIResponse/ response) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>// implement resource here
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>//gs.info(request.body.dataString);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>response = request.body.dataString;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>var gr = new GlideRecord(&amp;#39;change_request&amp;#39;);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gr.initialize();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>var parser = new JSONParser();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>var parsedData = parser.parse(response);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>//gs.info(parsedData);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gs.info(parsedData.application);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gr.short_description = parsedData.application;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gr.description = parsedData.description;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>//gr.change_request = current.sys_id;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gr.insert();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>})(request, response);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Keep in mind that this only works if the webhook sends the proper data.&lt;/p>
&lt;p>In the example script, the &lt;strong>response&lt;/strong> object is the JSON payload from the webhook. Whenever you see ‘gs.info()’, it is how you can write to the ServiceNow System Log. Use this as a debug tool as it allows you to write to the log the values found in the payload. The example script expects at least two key-pair values in the JSON payload, one key being &lt;code>application&lt;/code> and the other &lt;code>description&lt;/code>. In this example, the value for the &lt;code>application&lt;/code> key is being set to the &lt;strong>Short Description of the Change&lt;/strong>. The value associated with the &lt;strong>description&lt;/strong> key goes in the &lt;strong>Description&lt;/strong> field.&lt;/p>
&lt;h2 id="servicenow-rest-api">ServiceNow REST API&lt;/h2>
&lt;p>ServiceNow also has a REST API. You can use ServiceNow&amp;rsquo;s REST API Explorer to view sample code for any REST API call, including creating a change request.&lt;/p>
&lt;h2 id="servicenow-workflows">ServiceNow Workflows&lt;/h2>
&lt;p>While most people are familiar with ServiceNow as a ‘ticketing system’, it also has an automation engine. RunBooks for this engine are created as workflows. These workflows can automate internal ServiceNow operations (like handling approval routing) as well as calling other systems APIs (called Orchestrations), like provisioning VMs on-premise or in the cloud.&lt;/p>
&lt;p>These workflows can be called from a ServiceNow script in a Scripted REST API.&lt;/p>
&lt;h2 id="setting-up-the-webhook-stage-in-spinnaker">Setting Up the Webhook Stage in Spinnaker&lt;/h2>
&lt;p>The next step is to either create a generic webhook stage or a custom stage.&lt;/p>
&lt;p>To create a custom stage, perform the following steps:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>In &lt;code>/home/spinnaker/.hal/default/profiles&lt;/code> on your Halyad pod, edit &lt;code>orca-local&lt;/code>. If the file does not exist, create it. Below are the contents of my orca-local.yaml that generated my custom ServiceNow stage:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">webhook&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">preconfigured&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#6272a4"># stage name in stage selector drop down&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">label&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;Create Change Request in ServiceNow&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># UI description for stage&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">description&lt;/span>: Creates Change Request in ServiceNow
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># stage &amp;#39;type&amp;#39; in stage definition&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">type&lt;/span>: createChangeSNOW
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Webhook type&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">method&lt;/span>: POST
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># URL for webhook call&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">url&lt;/span>: https://dev102110.service-now.com/api/77303/spinnakerwebhooklistener
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">customHeaders&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Any necessary headers (supports S3 / Vault)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Authorization: Basic c2VydmljZWFjY291bnQ6cGFzc3dvcmQK&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">Content-Type&lt;/span>: application/json
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Payload for the request&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">payload&lt;/span>: |-&lt;span style="color:#f1fa8c">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;application&amp;#34;: &amp;#34;${trigger\[&amp;#39;artifacts&amp;#39;\][0][&amp;#39;reference&amp;#39;]}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;description&amp;#34;: &amp;#34;${parameterValues[&amp;#39;description&amp;#39;]}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> }&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Zero or more parameters&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">parameters&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">label&lt;/span>: Description (optional)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: description
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">description&lt;/span>: Enter a description for the ServiceNow Change Request
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">type&lt;/span>: string
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note that the example payload contains the two key/pair values that ServiceNow is expecting.&lt;/p>
&lt;p>The application is going to be the artifact that is triggering the pipeline. In the example, the pipeline is triggered when a new version of a container for a given organization or application is pushed to the configured Docker Registry. Artifactory is configured as the Docker Registry, so the application is set to something that follows a similar format: &lt;code>&amp;lt;jfrog server-reponame-jfrog.io/&amp;lt;orgname&amp;gt;/ &amp;lt;application&amp;gt;:&amp;lt;tag&amp;gt;&lt;/code>.&lt;/p>
&lt;p>The above is an example of using Pipeline Expressions to pass dynamic values. The description is an example of passing values that the user can enter in the stage when it is configured.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Apply your changes to Spinnaker: &lt;code>hal deploy apply&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Once you apply your changes, open Deck, Spinnaker&amp;rsquo;s UI.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>When you create or edit a pipeline, a new stage available is available:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-stage.png"/>
&lt;/figure>
&lt;p>If the new stage does not appear, perform a hard refresh or clear your browser cache and reopen Deck.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Other Spinnaker users can use the ServiceNow stage you created.&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-stage-2.png"/>
&lt;/figure>
&lt;p>The following screenshot shows a Change Request in ServiceNow created by the custom webhook stage:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-cr-from-spinn.png"/>
&lt;/figure>
&lt;h2 id="triggering-a-pipeline-based-on-webhooks">Triggering a pipeline based on webhooks&lt;/h2>
&lt;p>Another use case is to trigger a pipeline when a ticket gets approved. For many users, a deployment into production cannot happen unless there is an approval in ServiceNow.&lt;/p>
&lt;p>At it’s simplest implementation, an approval can trigger a pipeline execution. A more complex implementation could take fields from the ticket being approved and passed them to the pipeline as parameters to guide the deployment.&lt;/p>
&lt;p>The following screenshot shows a pipeline with that gets triggered based on a webhook:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-webhook-trigger.png"/>
&lt;/figure>
&lt;p>You can add payload constraints to avoid webhooks without the right payload from being processed. Armory recommends testing the webhook without contraints first.&lt;/p>
&lt;p>On the ServiceNow side, you need something to call this URL. In the example environment, there is a button on the Change Request form in ServiceNow that calls the URL.&lt;/p>
&lt;p>The first step is to define the REST call you need to make. To do this, type ‘REST’ on the navigation filter box and, from the results, select &lt;strong>System Web Services&lt;/strong> &amp;gt; &lt;strong>Outbound&lt;/strong> &amp;gt; &lt;strong>REST Message&lt;/strong>:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-outbound-rest.png"/>
&lt;/figure>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: On the menu shown above, select REST API Explorer to get code samples on how to use the ServiceNow REST API to create, search, or edit objects in ServiceNow.&lt;/p>
&lt;/blockquote>
&lt;p>In the &lt;strong>REST Messages&lt;/strong> window, create a new REST Message. The following image shows an example to trigger the pipeline.&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-rest-msg-1.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/integrations-snow-rest-msg-2.png"/>
&lt;/figure>
&lt;p>Once you have the REST Message set up, configure something to call it. Examples include when a ticket transitions as a step in a workflow or orchestration or a button or link on a form. This example uses a button in the form. Type “change” in the navigation filter as shown in the following image:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-filter-change.png"/>
&lt;/figure>
&lt;p>Click on &lt;strong>Change&lt;/strong> &amp;gt; &lt;strong>Open&lt;/strong> to get a list of all open Change Requests. Open any of Change Request from the list and right click on the top of the form as shown below to select &lt;strong>Configure&lt;/strong> &amp;gt; &lt;strong>UI Actions&lt;/strong>:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-ui-actions.png"/>
&lt;/figure>
&lt;p>The following screenshot shows how a UI action can be configured:&lt;/p>
&lt;figure>
&lt;img src="/images/integrations-snow-ui-actions-configure.png"/>
&lt;/figure>
&lt;p>Note that you can use the &lt;strong>Condition&lt;/strong> field to determine under which conditions the button should be active, such as when the status is “Ready for Approval”.&lt;/p></description></item><item><title>Continuous-Deployment: Observability</title><link>/continuous-deployment/armory-admin/observe/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/observe/</guid><description/></item><item><title>Continuous-Deployment: Rate Limiting the Spinnaker API</title><link>/continuous-deployment/armory-admin/rate-limit/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/rate-limit/</guid><description>
&lt;h2 id="how-spinnaker-monitors-a-deployment">How Spinnaker monitors a deployment&lt;/h2>
&lt;p>Spinnaker polls the entire state of managed cloud resources every 30 seconds through the Clouddriver service. The polling can cause cloud providers, such as AWS, to throttle the requests on your account. If you have a large number of Auto-Scaling Groups and Elastic Load Balancers in your account or other services commonly querying the same APIs then you can expect to see throttling exceptions in your Spinnaker logs.&lt;/p>
&lt;h3 id="how-to-alleviate-aws-throttling-exceptions">How to alleviate AWS throttling exceptions&lt;/h3>
&lt;p>There are several things you can do to help reduce the effects of throttling:&lt;/p>
&lt;ul>
&lt;li>Set fine tune rate limits within Spinnaker.&lt;/li>
&lt;li>Adjust Spinnaker&amp;rsquo;s retry limit per request.&lt;/li>
&lt;li>Decrease the polling interval.&lt;/li>
&lt;/ul>
&lt;h2 id="fine-grained-rate-limits">Fine-grained rate limits&lt;/h2>
&lt;p>Spinnaker queries your Cloud Provider (AWS, GCP, Azure, Kubernetes, etc) frequently to understand the state of your existing infrastructure and current deployments. However, this might cause you to run into rate limits imposed by the Cloud Provider. To help avoid this Spinnaker provides controls to limit the number of requests it generates. The unit used for these controls is &amp;ldquo;requests per second&amp;rdquo; (a double float value). Global defaults are &lt;code>10.0&lt;/code> max requests per second.&lt;/p>
&lt;p>Below is an example configuration for global rate limits for all services that you would place in your &lt;code>SpinnakerService&lt;/code> manifest under section &lt;code>spec.spinnakerConfig.profiles.clouddriver&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">serviceLimits&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you have multiple Cloud Providers, you can limit each one differently:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">serviceLimits&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">cloudProviderOverrides&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">aws&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can provide account specific overrides as well in case you have significantly more resources in one account while others have less:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">serviceLimits&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accountOverrides&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">my-test&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">my-prod&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, you can have more fine-grained control for particular AWS endpoints that might have a different rate limits.&lt;/p>
&lt;p>We&amp;rsquo;ve found that this formula works pretty well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>max_req_second = num_of_x_resources / clouddriver_30s_poll_interval
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For example, if we have 90 load balancers and clouddriver polls every 30 seconds, then we&amp;rsquo;ll end up with a rate limit of 3 reqs/second for &lt;code>AmazonElasticLoadBalancing&lt;/code>.&lt;/p>
&lt;p>Here&amp;rsquo;s the list of rate limits you can adjust created from &lt;a href="https://github.com/spinnaker/clouddriver/blob/v5.36.0/clouddriver-aws/src/main/groovy/com/netflix/spinnaker/clouddriver/aws/security/AmazonClientProvider.java">AmazonClientProvider.java@v5.36.0&lt;/a> on 05/14/2019 by using the regex &lt;code>\w+\.class&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">serviceLimits&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">implementationLimits&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSApplicationAutoScaling&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSApplicationAutoScalingClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSLambda&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSLambdaAsync&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSLambdaAsyncClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSLambdaClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSSecretsManager&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSSecretsManagerClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSServiceDiscovery&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSServiceDiscoveryClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSShield&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AWSShieldClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonAutoScaling&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonAutoScalingClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonCloudFormation&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonCloudFormationClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonCloudWatch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonCloudWatchClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonEC2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonEC2ClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonECR&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonECRClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonECS&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonECSClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonElasticLoadBalancing&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonElasticLoadBalancingClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonIdentityManagement&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonIdentityManagementClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonRoute53&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonRoute53ClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonS3&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonS3ClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonSNS&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonSNSClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonSQS&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonSQSClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonSimpleWorkflow&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">AmazonSimpleWorkflowClientBuilder&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">defaults&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">rateLimit&lt;/span>: &lt;span style="color:#bd93f9">10.0&lt;/span> &lt;span style="color:#6272a4"># default max req/second&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Using these settings will help you avoid hitting the AWS rate limits. They can also help Spinnaker be more responsive since the cloud provider clients will not implement their back-off strategy to continue to query the infrastructure.&lt;/p>
&lt;h2 id="request-retry">Request retry&lt;/h2>
&lt;p>You can set the number of retries per request with the following setting:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">aws&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">client&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">maxErrorRetry&lt;/span>: &lt;span style="color:#bd93f9">3&lt;/span> &lt;span style="color:#6272a4"># default&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is the number of retries before the request fails. It&amp;rsquo;s used with an exponential backoff, maxing out at 20 seconds.&lt;/p>
&lt;h2 id="fiat-hitting-rate-limits">Fiat hitting rate limits&lt;/h2>
&lt;p>If Fiat is configured to poll Github or Google, you may end up seeing rate limits when Fiat does its polling for user groups. Some symptoms that you might see are:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>You can&amp;rsquo;t log into Spinnaker anymore&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Your Fiat logs contain lines similar to:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>GithubTeamsUserRolesProvider : [] HTTP 403 Forbidden. Rate limit info: X-RateLimit-Limit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GoogleDirectoryUserRolesProvider : [] Failed to fetch groups for user x: Rate Limit Exceeded
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;p>To address this issue, adjust poll cycle time and/or timeouts in your &lt;code>SpinnakerService&lt;/code> manifest under section &lt;code>spec.spinnakerConfig.profiles.fiat&lt;/code> (beware: you will end up with two nested &lt;code>fiat&lt;/code> sections). See (&lt;a href="https://github.com/spinnaker/fiat/blob/v1.7.0/fiat-web/src/main/java/com/netflix/spinnaker/fiat/config/FiatServerConfigurationProperties.java">FiatServerConfigurationProperties.java for more details&lt;/a>).:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">fiat&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">writeMode&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Poll cycle interval, &amp;#34;check if a user belongs to a group every X ms&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">syncDelayMs&lt;/span>: &lt;span style="color:#bd93f9">600000&lt;/span> &lt;span style="color:#6272a4"># the default 600000 (10 mins) is usually fine&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># How much time to between retries of dependent resource providers if they are down.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">retryIntervalMs&lt;/span>: &lt;span style="color:#bd93f9">10000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="faq">FAQ&lt;/h1>
&lt;p>&lt;em>Q:&lt;/em> Why doesn&amp;rsquo;t Spinnaker use AWS Config to update its state?&lt;/p>
&lt;p>&lt;em>A:&lt;/em> AWS Config does not support all resource types. The two most rate limited APIs are Auto Scaling and Classic Elastic Load Balancing, &lt;a href="http://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html">neither are supported&lt;/a> by AWS Config. Additionally, there is a non-trivial delay from the time a resource is created and the time a notification is created by AWS Config.&lt;/p></description></item><item><title>Continuous-Deployment: Restrict Application Creation</title><link>/continuous-deployment/armory-admin/fiat-create-permissions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/fiat-create-permissions/</guid><description>
&lt;h2 id="requirements-and-guidelines-for-using-fiat">Requirements and guidelines for using Fiat&lt;/h2>
&lt;ul>
&lt;li>Armory 2.17 (Open Source Spinnaker&lt;sup>TM&lt;/sup> 1.17) or later&lt;/li>
&lt;li>Fiat must be enabled and configured to work with an identity provider. For more information, see &lt;a href="https://www.spinnaker.io/setup/security/authorization/">Authorization (RBAC)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>When managing roles for Spinnaker, keep the following in mind:&lt;/p>
&lt;ul>
&lt;li>Roles are case insensitive. All roles are changed to lowercase in Fiat&amp;rsquo;s internal model.&lt;/li>
&lt;li>You must explicitly configure permissions for each user role. The default for a user role is no permissions, which means it cannot perform any actions.&lt;/li>
&lt;/ul>
&lt;h2 id="restrict-application-creation">Restrict application creation&lt;/h2>
&lt;p>To restrict which users can create applications in Spinnaker, perform the following steps:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Add the line &lt;code>auth.permissions.provider.application: aggregate&lt;/code> to &lt;code>SpinnakerService&lt;/code> manifest under key &lt;code>spec.spinnakerConfig.profiles.fiat&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Add prefixes as a source:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">auth.permissions.source.application.prefix&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Define the permissions for a prefix:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ff79c6">prefix&lt;/span>: &amp;lt;some_prefix&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">permissions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">READ&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;&amp;lt;user role 1&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;&amp;lt;user role 2&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;&amp;lt;user role n&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">WRITE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;&amp;lt;user role n&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">EXECUTE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;user role n&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here is an example configuration with in-line comments:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">profiles&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">fiat&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Enables Fiat to read from new sources.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">auth.permissions.provider.application&lt;/span>: aggregate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Sets `prefix` as one of these new sources&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">auth.permissions.source.application.prefix&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">prefixes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Defines the prefix `apptest-x`.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">prefix&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;apptest-*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">permissions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Defines permission requirements for all applications that match the prefix `apptest-*` based on roles.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># role-one and role-two have READ permission&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">READ&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-two&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># role-one has write permission&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">WRITE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># role-one has execute permission&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">EXECUTE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>As a result, any application that matches the prefix &lt;code>apptest-*&lt;/code> has restrictions on who can perform actions. For example, a user with the user role &lt;code>role-two&lt;/code> only has &lt;code>READ&lt;/code> permission.&lt;br>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>To restrict application creation specifically, add &lt;code>fiat.restrictApplicationCreation&lt;/code> at the top of fiat config and set it to &lt;code>true&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Note: Currently, the prefix source is the only source that support the CREATE permission.&lt;/strong>&lt;/p>
&lt;p>The following example builds upon the example from the previous steps. In-line comments describe additions:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: spinnaker.armory.io/v1alpha2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: SpinnakerService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: spinnaker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">spinnakerConfig&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">profiles&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">fiat&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Add CREATE as a permission&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">fiat.restrictApplicationCreation&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">auth.permissions.provider.application&lt;/span>: aggregate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">auth.permissions.source.application.prefix&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">prefixes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">prefix&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">permissions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6272a4"># Assign CREATE permission to role-one&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">CREATE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">READ&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-two&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">WRITE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">EXECUTE&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f1fa8c">&amp;#34;role-one&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above example assigns CREATE permission to users with the &lt;code>role-one&lt;/code> role. Users without the &lt;code>role-one&lt;/code> role cannot create any applications in Spinnaker.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Apply your configuration changes to Spinnaker by running the following command: &lt;code>kubectl -n &amp;lt;spinnaker namespace&amp;gt; apply -f &amp;lt;SpinnakerService manifest&amp;gt;&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>The following screenshot shows what happens when a user without sufficient permissions attempts to create an application in Deck, Spinnaker&amp;rsquo;s UI:&lt;/p>
&lt;figure>
&lt;img src="/images/authz_create_permission.png"/>
&lt;/figure></description></item><item><title>Continuous-Deployment: Spinnaker Production Environments</title><link>/continuous-deployment/armory-admin/spinnaker-production-environments/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/spinnaker-production-environments/</guid><description>
&lt;h2 id="architecture">Architecture&lt;/h2>
&lt;ul>
&lt;li>Use MySQL compatible database engine
&lt;ul>
&lt;li>Managed services like Aurora provide cross-region replication&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Kubernetes
&lt;ul>
&lt;li>See &lt;a href="/continuous-deployment/installation/system-requirements/">System Requirements&lt;/a> for more information&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Each service has at least 2 replicas to provide basic availability at the Kubernetes level&lt;/li>
&lt;li>Monitoring is optional but strongly recommended&lt;/li>
&lt;li>Armory provides optional log Spinnaker aggregation for troubleshooting but we also recommend customers to have a log management solution in place&lt;/li>
&lt;/ul>
&lt;figure>
&lt;img src="/images/prod-recommendations/prod-architecture.png"/>
&lt;/figure>
&lt;h3 id="kubernetes-considerations">Kubernetes Considerations&lt;/h3>
&lt;ul>
&lt;li>The Kubernetes cluster sizing recommendations assume that only Spinnaker, its monitoring, and the Kubernetes operator run in the cluster. It also provides extra room for rolling deployments of Spinnaker itself.&lt;/li>
&lt;li>If available, use a cluster with nodes in different availability zones.&lt;/li>
&lt;li>It’s generally better to go with more smaller nodes than fewer larger nodes for the cluster to be more resilient to the loss of nodes. Make sure that nodes are still able to handle the largest pods in terms of CPU and memory.&lt;/li>
&lt;/ul>
&lt;h3 id="database-considerations">Database Considerations&lt;/h3>
&lt;ul>
&lt;li>If available, use cross-region replication to ensure durability of the data stored.
&lt;ul>
&lt;li>Front50’s database contains pipeline definitions and needs to be properly backed up.&lt;/li>
&lt;li>Orca’s database contains pipeline execution history that is displayed in Spinnaker’s UI.&lt;/li>
&lt;li>Clouddriver’s database contain your infrastructure cache. If lost, it will need to be re-cached which depending on the size of your infrastructure may take a while. It doesn’t have long term value.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Make sure the network latency between Spinnaker and the database cluster is reasonable. It often just means located in the same datacenter.&lt;/li>
&lt;li>Clouddriver, Orca, and Front50 services must each use a different database. They can be in different database clusters or in the same. A single cluster is easier to manage and more cost effective but the number of connections used by Spinnaker will be added across all services.
&lt;ul>
&lt;li>Your database cluster must support the number of open connections from Spinnaker and any other tool you need. For numbers refer to the database connections chart in the profiles below.&lt;/li>
&lt;li>Clouddriver connection pools can be tuned via sql.connectionPools.cacheWriter.maxPoolSize and sql.connectionPools.default.maxPoolSize. Both values default to 20 and need to be increased to handle more tasks per Clouddriver.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="redis-considerations">Redis Considerations&lt;/h3>
&lt;p>Most services rely on Redis for lightweight storage and/or task coordination. Spinnaker does not store many items in Redis as is reflected in the following recommendations. Redis being single threaded doesn’t need more than one CPU.&lt;/p>
&lt;p>When available, a managed Redis (like ElastiCache) can be used. A shared Redis can be used for ease of management.&lt;/p>
&lt;h3 id="spinnaker-settings">Spinnaker Settings&lt;/h3>
&lt;p>To support a high number of API requests, we advise to set the following settings in gate and front50 profiles:&lt;/p>
&lt;p>hystrix.threadpool.default.coreSize: x&lt;/p>
&lt;p>Where x is given by: maximum API request per seconds * mean response time&lt;/p>
&lt;p>We estimated the maximum API request per seconds in the tests below, refer to the Average API Response Time graph below. For instance for 30 request/sec, the coreSize value could be set to: 300 * 0.25 = 75.&lt;/p>
&lt;h2 id="recommendations">Recommendations&lt;/h2>
&lt;h3 id="installation-types">Installation Types&lt;/h3>
&lt;p>Many factors come to sizing Spinnaker, for instance:&lt;/p>
&lt;ul>
&lt;li>Number of active users will impact how to size Gate service.&lt;/li>
&lt;li>Complex pipelines will impact the amount of work the Orca service has to do.&lt;/li>
&lt;li>Different providers (Kubernetes, GCP, AWS,…) come with very different execution profiles for the Clouddriver service.&lt;/li>
&lt;/ul>
&lt;p>This document makes the following assumptions:&lt;/p>
&lt;ul>
&lt;li>Pipelines used to evaluate Spinnaker are simple and made of a Deploy and 2 Wait stages for stage scheduling. If you expect your pipelines to be complex, divide the supported executions by the number of non-trivial expected stages (baking, deploying) in your pipelines.&lt;/li>
&lt;li>API requests simulate potential tool requests as well as user activity. We give number of concurrent users.&lt;/li>
&lt;li>All services run with at least 2 replicas for basic availability. It is possible to run with fewer replicas at the cost of potential outages.&lt;/li>
&lt;/ul>
&lt;h2 id="base-profile---kubernetes-deployments">Base Profile - Kubernetes Deployments&lt;/h2>
&lt;h3 id="base-profile-recommendations">Base profile recommendations&lt;/h3>
&lt;p>A base deployment of Spinnaker targets organizations with:&lt;/p>
&lt;ul>
&lt;li>50 applications&lt;/li>
&lt;li>250 deployments per day over 5 hour window.&lt;/li>
&lt;li>30 req/s coming from browser sessions or tools&lt;/li>
&lt;li>10x burst for both pipelines and API calls.&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;strong>Service&lt;/strong>&lt;/th>
&lt;th>&lt;strong>Replicas&lt;/strong>&lt;/th>
&lt;th>&lt;strong>CPU request&lt;/strong>&lt;/th>
&lt;th>&lt;strong>CPU limit&lt;/strong>&lt;/th>
&lt;th>&lt;strong>Memory request&lt;/strong>&lt;/th>
&lt;th>&lt;strong>Memory limits&lt;/strong>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Clouddriver&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>2000m&lt;/td>
&lt;td>3000m&lt;/td>
&lt;td>2.0Gi&lt;/td>
&lt;td>2.5Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Deck&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>150m&lt;/td>
&lt;td>300m&lt;/td>
&lt;td>32Mi&lt;/td>
&lt;td>64Mi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Dinghy&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Echo&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;td>1.5Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Fiat&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Front50&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;td>1.5Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Gate&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>750m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;td>1.5Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Kayenta&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Igor&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Orca&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>1500m&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;td>1.5Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Rosco&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Terraformer&lt;/strong>&lt;/td>
&lt;td>2&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Redis&lt;/strong>&lt;/td>
&lt;td>1&lt;/td>
&lt;td>500m&lt;/td>
&lt;td>1000m&lt;/td>
&lt;td>0.5Gi&lt;/td>
&lt;td>1.0Gi&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Total&lt;/strong>&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;strong>16300m&lt;/strong>&lt;/td>
&lt;td>&lt;strong>28600m&lt;/strong>&lt;/td>
&lt;td>&lt;strong>18.56Gi&lt;/strong>&lt;/td>
&lt;td>&lt;strong>31.125Gi&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="load-test-base-profile-kubernetes">Load Test: Base Profile (Kubernetes)&lt;/h2>
&lt;h3 id="overview">Overview&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;strong>Armory Spinnaker&lt;/strong>&lt;/th>
&lt;th>&lt;strong>API request/sec - baseline (burst)&lt;/strong>&lt;/th>
&lt;th>&lt;strong>Pipeline trigger/minute - baseline (burst)&lt;/strong>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>2.17.1&lt;/strong>&lt;/td>
&lt;td>30 (300)&lt;/td>
&lt;td>0.834 (8.34)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>
&lt;figure>
&lt;img src="/images/prod-recommendations/pipeline-api-calls.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/cpu-quota.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/total-memory.png"/>
&lt;/figure>
&lt;/p>
&lt;h3 id="general-service-health">General Service Health&lt;/h3>
&lt;figure>
&lt;img src="/images/prod-recommendations/general-service-health.png"/>
&lt;/figure>
&lt;h3 id="database-connections">Database Connections&lt;/h3>
&lt;figure>
&lt;img src="/images/prod-recommendations/db-connections.png"/>
&lt;/figure>
&lt;h3 id="per-service-cpu-and-memory">Per Service CPU and Memory&lt;/h3>
&lt;p>
&lt;figure>
&lt;img src="/images/prod-recommendations/clouddriver-container-cpu.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/clouddriver-jvm-usage.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/echo-container-cpu.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/echo-jvm-usage.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/front50-container-cpu.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/front50-jvm-usage.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/gate-container-cpu.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/gate-jvm-usage"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-container-cpu.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-jvm-usage.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/redis-container-cpu.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/redis-jvm-usage.png"/>
&lt;/figure>
&lt;/p>
&lt;h3 id="clouddriver-health">Clouddriver Health&lt;/h3>
&lt;p>
&lt;figure>
&lt;img src="/images/prod-recommendations/clouddriver-invocation-latency.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/kubectl-latency.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/avg-agent-time.png"/>
&lt;/figure>
&lt;/p>
&lt;h3 id="orca-health">Orca Health&lt;/h3>
&lt;p>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-queue-depth.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-controller-latency.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/stages-started.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-running-task-duration.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-stage-status.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/spin-queue.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/message-lag.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/orca-active-executions.png"/>
&lt;/figure>
&lt;/p>
&lt;h3 id="gate-health">Gate Health&lt;/h3>
&lt;p>
&lt;figure>
&lt;img src="/images/prod-recommendations/gate-latency.png"/>
&lt;/figure>
&lt;figure>
&lt;img src="/images/prod-recommendations/front50-latency.png"/>
&lt;/figure>
&lt;/p></description></item><item><title>Continuous-Deployment: Work with Secrets in Spinnaker</title><link>/continuous-deployment/armory-admin/secrets/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/continuous-deployment/armory-admin/secrets/</guid><description>
&lt;h2 id="overview-of-storing-secrets">Overview of storing secrets&lt;/h2>
&lt;p>Storing Spinnaker&lt;sup>TM&lt;/sup> configs in a git repository is a great solution for maintaining versions of your configurations, but storing secrets in plain text is a bad security practice. If you&amp;rsquo;re using the Operator to deploy Spinnaker, separating your secrets from your configs through end-to-end secrets management is already supported. All you need to do is replace secrets in the configuration files with the syntax described here, and Spinnaker will decrypt them as needed.&lt;/p>
&lt;p>We can now store secrets (tokens, passwords, sensitive files) separately from the Spinnaker configurations. We&amp;rsquo;ll provide references to these secrets to services that need them.&lt;/p>
&lt;ul>
&lt;li>Spinnaker services that support decryption will decrypt these secrets upon startup.&lt;/li>
&lt;li>Operator can decrypt these secrets when it needs to use them (e.g. when validating resources).&lt;/li>
&lt;li>Operator can send secret references to the services that support decryption or send decrypted secrets if the service does not support it.&lt;/li>
&lt;/ul>
&lt;h2 id="using-secrets">Using secrets&lt;/h2>
&lt;h3 id="secret-format">Secret format&lt;/h3>
&lt;p>When referencing string secrets (passwords, tokens) in configs, use the following general format:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>encrypted:&amp;lt;secret engine&amp;gt;!&amp;lt;key1&amp;gt;:&amp;lt;value1&amp;gt;!&amp;lt;key2&amp;gt;:&amp;lt;value2&amp;gt;!...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>When referencing files, the same parameters are used but with the &lt;code>encryptedFile&lt;/code> prefix:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>encryptedFile:&amp;lt;secret engine&amp;gt;!&amp;lt;key1&amp;gt;:&amp;lt;value1&amp;gt;!&amp;lt;key2&amp;gt;:&amp;lt;value2&amp;gt;!...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The keys and values making up the string vary with each secret engine. Refer to the specific documentation for each engine for more information.&lt;/p>
&lt;h3 id="in-main-configuration">In main configuration&lt;/h3>
&lt;p>This applies to section &lt;code>spec.spinnakerConfig.config&lt;/code> of the &lt;code>SpinnakerService&lt;/code> manifest when using the Operator.&lt;/p>
&lt;p>Operator can understand the secrets you provide. If the service you are deploying is able to decrypt secrets, Operator will pass the reference directly. Otherwise it will decrypt the configuration before sending it.&lt;/p>
&lt;p>For instance, after replacing the GitHub token in our main config with the encrypted syntax:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">github&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">token&lt;/span>: encrypted:s3!r:us-west-2!b:mybucket!f:spinnaker-secrets.yml!k:github.token
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You find the following in &lt;code>/opt/spinnaker/config/clouddriver.yml&lt;/code> inside clouddriver pod:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">github&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">token&lt;/span>: encrypted:s3!r:us-west-2!b:mybucket!f:spinnaker-secrets.yml!k:github.token
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And for an older release of Clouddriver that does not support decryption:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">github&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">enabled&lt;/span>: &lt;span style="color:#ff79c6">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">accounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ff79c6">name&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">token&lt;/span>: &amp;lt;TOKEN&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="in-other-configuration">In other configuration&lt;/h3>
&lt;p>You can also provide secret references directly in &lt;code>SpinnakerService&lt;/code> manifest under section &lt;code>spec.spinnakerConfig.profiles&lt;/code> when using the Operator as well as directly in Spinnaker services.&lt;/p>
&lt;h3 id="supported-secret-engines">Supported secret engines&lt;/h3>
&lt;p>Is there a secret engine you&amp;rsquo;d like us to support? Submit a feature request &lt;a href="mailto:hello@armory.io">here&lt;/a>!&lt;/p></description></item></channel></rss>