Avoid envs and extend CRDs with vault config; remove controller dependency completely
This commit is contained in:
		
							parent
							
								
									69dfa4e375
								
							
						
					
					
						commit
						c3ce54cabc
					
				|  | @ -59,7 +59,10 @@ type AutoscalingListenerSpec struct { | ||||||
| 	Proxy *ProxyConfig `json:"proxy,omitempty"` | 	Proxy *ProxyConfig `json:"proxy,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// +optional
 | 	// +optional
 | ||||||
| 	GitHubServerTLS *GitHubServerTLSConfig `json:"githubServerTLS,omitempty"` | 	GitHubServerTLS *TLSConfig `json:"githubServerTLS,omitempty"` | ||||||
|  | 
 | ||||||
|  | 	// +optional
 | ||||||
|  | 	VaultConfig *VaultConfig `json:"vaultConfig,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// +optional
 | 	// +optional
 | ||||||
| 	Metrics *MetricsConfig `json:"metrics,omitempty"` | 	Metrics *MetricsConfig `json:"metrics,omitempty"` | ||||||
|  | @ -98,7 +101,7 @@ func (l *AutoscalingListener) Proxy() *ProxyConfig { | ||||||
| 	return l.Spec.Proxy | 	return l.Spec.Proxy | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (l *AutoscalingListener) GitHubServerTLS() *GitHubServerTLSConfig { | func (l *AutoscalingListener) GitHubServerTLS() *TLSConfig { | ||||||
| 	return l.Spec.GitHubServerTLS | 	return l.Spec.GitHubServerTLS | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ import ( | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"github.com/actions/actions-runner-controller/hash" | 	"github.com/actions/actions-runner-controller/hash" | ||||||
|  | 	"github.com/actions/actions-runner-controller/vault" | ||||||
| 	"golang.org/x/net/http/httpproxy" | 	"golang.org/x/net/http/httpproxy" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | @ -69,7 +70,13 @@ type AutoscalingRunnerSetSpec struct { | ||||||
| 	Proxy *ProxyConfig `json:"proxy,omitempty"` | 	Proxy *ProxyConfig `json:"proxy,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// +optional
 | 	// +optional
 | ||||||
| 	GitHubServerTLS *GitHubServerTLSConfig `json:"githubServerTLS,omitempty"` | 	GitHubServerTLS *TLSConfig `json:"githubServerTLS,omitempty"` | ||||||
|  | 
 | ||||||
|  | 	// +optional
 | ||||||
|  | 	VaultServerTLS *TLSConfig `json:"vaultServerTLS,omitempty"` | ||||||
|  | 
 | ||||||
|  | 	// +optional
 | ||||||
|  | 	VaultConfig *VaultConfig `json:"vaultConfig,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// Required
 | 	// Required
 | ||||||
| 	Template corev1.PodTemplateSpec `json:"template,omitempty"` | 	Template corev1.PodTemplateSpec `json:"template,omitempty"` | ||||||
|  | @ -89,12 +96,12 @@ type AutoscalingRunnerSetSpec struct { | ||||||
| 	MinRunners *int `json:"minRunners,omitempty"` | 	MinRunners *int `json:"minRunners,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type GitHubServerTLSConfig struct { | type TLSConfig struct { | ||||||
| 	// Required
 | 	// Required
 | ||||||
| 	CertificateFrom *TLSCertificateSource `json:"certificateFrom,omitempty"` | 	CertificateFrom *TLSCertificateSource `json:"certificateFrom,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *GitHubServerTLSConfig) ToCertPool(keyFetcher func(name, key string) ([]byte, error)) (*x509.CertPool, error) { | func (c *TLSConfig) ToCertPool(keyFetcher func(name, key string) ([]byte, error)) (*x509.CertPool, error) { | ||||||
| 	if c.CertificateFrom == nil { | 	if c.CertificateFrom == nil { | ||||||
| 		return nil, fmt.Errorf("certificateFrom not specified") | 		return nil, fmt.Errorf("certificateFrom not specified") | ||||||
| 	} | 	} | ||||||
|  | @ -235,6 +242,26 @@ type ProxyServerConfig struct { | ||||||
| 	CredentialSecretRef string `json:"credentialSecretRef,omitempty"` | 	CredentialSecretRef string `json:"credentialSecretRef,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type VaultConfig struct { | ||||||
|  | 	// +optional
 | ||||||
|  | 	Type vault.VaultType `json:"type,omitempty"` | ||||||
|  | 	// +optional
 | ||||||
|  | 	AzureKeyVault *AzureKeyVaultConfig `json:"azureKeyVault,omitempty"` | ||||||
|  | 	// +optional
 | ||||||
|  | 	Proxy *ProxyConfig `json:"proxy,omitempty"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type AzureKeyVaultConfig struct { | ||||||
|  | 	// +required
 | ||||||
|  | 	URL string `json:"url,omitempty"` | ||||||
|  | 	// +required
 | ||||||
|  | 	TenantID string `json:"tenantId,omitempty"` | ||||||
|  | 	// +required
 | ||||||
|  | 	ClientID string `json:"clientId,omitempty"` | ||||||
|  | 	// +required
 | ||||||
|  | 	CertificatePath string `json:"certificatePath,omitempty"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // MetricsConfig holds configuration parameters for each metric type
 | // MetricsConfig holds configuration parameters for each metric type
 | ||||||
| type MetricsConfig struct { | type MetricsConfig struct { | ||||||
| 	// +optional
 | 	// +optional
 | ||||||
|  | @ -293,11 +320,15 @@ func (ars *AutoscalingRunnerSet) GitHubConfigUrl() string { | ||||||
| 	return ars.Spec.GitHubConfigUrl | 	return ars.Spec.GitHubConfigUrl | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ars *AutoscalingRunnerSet) VaultConfig() *VaultConfig { | ||||||
|  | 	return ars.Spec.VaultConfig | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (ars *AutoscalingRunnerSet) Proxy() *ProxyConfig { | func (ars *AutoscalingRunnerSet) Proxy() *ProxyConfig { | ||||||
| 	return ars.Spec.Proxy | 	return ars.Spec.Proxy | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ars *AutoscalingRunnerSet) GitHubServerTLS() *GitHubServerTLSConfig { | func (ars *AutoscalingRunnerSet) GitHubServerTLS() *TLSConfig { | ||||||
| 	return ars.Spec.GitHubServerTLS | 	return ars.Spec.GitHubServerTLS | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -308,7 +339,7 @@ func (ars *AutoscalingRunnerSet) RunnerSetSpecHash() string { | ||||||
| 		RunnerGroup        string | 		RunnerGroup        string | ||||||
| 		RunnerScaleSetName string | 		RunnerScaleSetName string | ||||||
| 		Proxy              *ProxyConfig | 		Proxy              *ProxyConfig | ||||||
| 		GitHubServerTLS    *GitHubServerTLSConfig | 		GitHubServerTLS    *TLSConfig | ||||||
| 		Template           corev1.PodTemplateSpec | 		Template           corev1.PodTemplateSpec | ||||||
| 	} | 	} | ||||||
| 	spec := &runnerSetSpec{ | 	spec := &runnerSetSpec{ | ||||||
|  |  | ||||||
|  | @ -79,10 +79,14 @@ func (er *EphemeralRunner) Proxy() *ProxyConfig { | ||||||
| 	return er.Spec.Proxy | 	return er.Spec.Proxy | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (er *EphemeralRunner) GitHubServerTLS() *GitHubServerTLSConfig { | func (er *EphemeralRunner) GitHubServerTLS() *TLSConfig { | ||||||
| 	return er.Spec.GitHubServerTLS | 	return er.Spec.GitHubServerTLS | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ars *EphemeralRunner) VaultConfig() *VaultConfig { | ||||||
|  | 	return ars.Spec.VaultConfig | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // EphemeralRunnerSpec defines the desired state of EphemeralRunner
 | // EphemeralRunnerSpec defines the desired state of EphemeralRunner
 | ||||||
| type EphemeralRunnerSpec struct { | type EphemeralRunnerSpec struct { | ||||||
| 	// +required
 | 	// +required
 | ||||||
|  | @ -101,7 +105,10 @@ type EphemeralRunnerSpec struct { | ||||||
| 	ProxySecretRef string `json:"proxySecretRef,omitempty"` | 	ProxySecretRef string `json:"proxySecretRef,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// +optional
 | 	// +optional
 | ||||||
| 	GitHubServerTLS *GitHubServerTLSConfig `json:"githubServerTLS,omitempty"` | 	GitHubServerTLS *TLSConfig `json:"githubServerTLS,omitempty"` | ||||||
|  | 
 | ||||||
|  | 	// +optional
 | ||||||
|  | 	VaultConfig *VaultConfig `json:"vaultConfig,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	corev1.PodTemplateSpec `json:",inline"` | 	corev1.PodTemplateSpec `json:",inline"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -72,10 +72,14 @@ func (ers *EphemeralRunnerSet) Proxy() *ProxyConfig { | ||||||
| 	return ers.Spec.EphemeralRunnerSpec.Proxy | 	return ers.Spec.EphemeralRunnerSpec.Proxy | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ers *EphemeralRunnerSet) GitHubServerTLS() *GitHubServerTLSConfig { | func (ers *EphemeralRunnerSet) GitHubServerTLS() *TLSConfig { | ||||||
| 	return ers.Spec.EphemeralRunnerSpec.GitHubServerTLS | 	return ers.Spec.EphemeralRunnerSpec.GitHubServerTLS | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ars *EphemeralRunnerSet) VaultConfig() *VaultConfig { | ||||||
|  | 	return ars.Spec.EphemeralRunnerSpec.VaultConfig | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // EphemeralRunnerSetList contains a list of EphemeralRunnerSet
 | // EphemeralRunnerSetList contains a list of EphemeralRunnerSet
 | ||||||
| // +kubebuilder:object:root=true
 | // +kubebuilder:object:root=true
 | ||||||
| type EphemeralRunnerSetList struct { | type EphemeralRunnerSetList struct { | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| func TestGitHubServerTLSConfig_ToCertPool(t *testing.T) { | func TestGitHubServerTLSConfig_ToCertPool(t *testing.T) { | ||||||
| 	t.Run("returns an error if CertificateFrom not specified", func(t *testing.T) { | 	t.Run("returns an error if CertificateFrom not specified", func(t *testing.T) { | ||||||
| 		c := &v1alpha1.GitHubServerTLSConfig{ | 		c := &v1alpha1.TLSConfig{ | ||||||
| 			CertificateFrom: nil, | 			CertificateFrom: nil, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -29,7 +29,7 @@ func TestGitHubServerTLSConfig_ToCertPool(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	t.Run("returns an error if CertificateFrom.ConfigMapKeyRef not specified", func(t *testing.T) { | 	t.Run("returns an error if CertificateFrom.ConfigMapKeyRef not specified", func(t *testing.T) { | ||||||
| 		c := &v1alpha1.GitHubServerTLSConfig{ | 		c := &v1alpha1.TLSConfig{ | ||||||
| 			CertificateFrom: &v1alpha1.TLSCertificateSource{}, | 			CertificateFrom: &v1alpha1.TLSCertificateSource{}, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +41,7 @@ func TestGitHubServerTLSConfig_ToCertPool(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	t.Run("returns a valid cert pool with correct configuration", func(t *testing.T) { | 	t.Run("returns a valid cert pool with correct configuration", func(t *testing.T) { | ||||||
| 		c := &v1alpha1.GitHubServerTLSConfig{ | 		c := &v1alpha1.TLSConfig{ | ||||||
| 			CertificateFrom: &v1alpha1.TLSCertificateSource{ | 			CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 				ConfigMapKeyRef: &v1.ConfigMapKeySelector{ | 				ConfigMapKeyRef: &v1.ConfigMapKeySelector{ | ||||||
| 					LocalObjectReference: v1.LocalObjectReference{ | 					LocalObjectReference: v1.LocalObjectReference{ | ||||||
|  |  | ||||||
|  | @ -100,7 +100,12 @@ func (in *AutoscalingListenerSpec) DeepCopyInto(out *AutoscalingListenerSpec) { | ||||||
| 	} | 	} | ||||||
| 	if in.GitHubServerTLS != nil { | 	if in.GitHubServerTLS != nil { | ||||||
| 		in, out := &in.GitHubServerTLS, &out.GitHubServerTLS | 		in, out := &in.GitHubServerTLS, &out.GitHubServerTLS | ||||||
| 		*out = new(GitHubServerTLSConfig) | 		*out = new(TLSConfig) | ||||||
|  | 		(*in).DeepCopyInto(*out) | ||||||
|  | 	} | ||||||
|  | 	if in.VaultConfig != nil { | ||||||
|  | 		in, out := &in.VaultConfig, &out.VaultConfig | ||||||
|  | 		*out = new(VaultConfig) | ||||||
| 		(*in).DeepCopyInto(*out) | 		(*in).DeepCopyInto(*out) | ||||||
| 	} | 	} | ||||||
| 	if in.Metrics != nil { | 	if in.Metrics != nil { | ||||||
|  | @ -209,7 +214,17 @@ func (in *AutoscalingRunnerSetSpec) DeepCopyInto(out *AutoscalingRunnerSetSpec) | ||||||
| 	} | 	} | ||||||
| 	if in.GitHubServerTLS != nil { | 	if in.GitHubServerTLS != nil { | ||||||
| 		in, out := &in.GitHubServerTLS, &out.GitHubServerTLS | 		in, out := &in.GitHubServerTLS, &out.GitHubServerTLS | ||||||
| 		*out = new(GitHubServerTLSConfig) | 		*out = new(TLSConfig) | ||||||
|  | 		(*in).DeepCopyInto(*out) | ||||||
|  | 	} | ||||||
|  | 	if in.VaultServerTLS != nil { | ||||||
|  | 		in, out := &in.VaultServerTLS, &out.VaultServerTLS | ||||||
|  | 		*out = new(TLSConfig) | ||||||
|  | 		(*in).DeepCopyInto(*out) | ||||||
|  | 	} | ||||||
|  | 	if in.VaultConfig != nil { | ||||||
|  | 		in, out := &in.VaultConfig, &out.VaultConfig | ||||||
|  | 		*out = new(VaultConfig) | ||||||
| 		(*in).DeepCopyInto(*out) | 		(*in).DeepCopyInto(*out) | ||||||
| 	} | 	} | ||||||
| 	in.Template.DeepCopyInto(&out.Template) | 	in.Template.DeepCopyInto(&out.Template) | ||||||
|  | @ -260,6 +275,21 @@ func (in *AutoscalingRunnerSetStatus) DeepCopy() *AutoscalingRunnerSetStatus { | ||||||
| 	return out | 	return out | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||||
|  | func (in *AzureKeyVaultConfig) DeepCopyInto(out *AzureKeyVaultConfig) { | ||||||
|  | 	*out = *in | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureKeyVaultConfig.
 | ||||||
|  | func (in *AzureKeyVaultConfig) DeepCopy() *AzureKeyVaultConfig { | ||||||
|  | 	if in == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	out := new(AzureKeyVaultConfig) | ||||||
|  | 	in.DeepCopyInto(out) | ||||||
|  | 	return out | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||||
| func (in *CounterMetric) DeepCopyInto(out *CounterMetric) { | func (in *CounterMetric) DeepCopyInto(out *CounterMetric) { | ||||||
| 	*out = *in | 	*out = *in | ||||||
|  | @ -439,7 +469,12 @@ func (in *EphemeralRunnerSpec) DeepCopyInto(out *EphemeralRunnerSpec) { | ||||||
| 	} | 	} | ||||||
| 	if in.GitHubServerTLS != nil { | 	if in.GitHubServerTLS != nil { | ||||||
| 		in, out := &in.GitHubServerTLS, &out.GitHubServerTLS | 		in, out := &in.GitHubServerTLS, &out.GitHubServerTLS | ||||||
| 		*out = new(GitHubServerTLSConfig) | 		*out = new(TLSConfig) | ||||||
|  | 		(*in).DeepCopyInto(*out) | ||||||
|  | 	} | ||||||
|  | 	if in.VaultConfig != nil { | ||||||
|  | 		in, out := &in.VaultConfig, &out.VaultConfig | ||||||
|  | 		*out = new(VaultConfig) | ||||||
| 		(*in).DeepCopyInto(*out) | 		(*in).DeepCopyInto(*out) | ||||||
| 	} | 	} | ||||||
| 	in.PodTemplateSpec.DeepCopyInto(&out.PodTemplateSpec) | 	in.PodTemplateSpec.DeepCopyInto(&out.PodTemplateSpec) | ||||||
|  | @ -497,26 +532,6 @@ func (in *GaugeMetric) DeepCopy() *GaugeMetric { | ||||||
| 	return out | 	return out | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 |  | ||||||
| func (in *GitHubServerTLSConfig) DeepCopyInto(out *GitHubServerTLSConfig) { |  | ||||||
| 	*out = *in |  | ||||||
| 	if in.CertificateFrom != nil { |  | ||||||
| 		in, out := &in.CertificateFrom, &out.CertificateFrom |  | ||||||
| 		*out = new(TLSCertificateSource) |  | ||||||
| 		(*in).DeepCopyInto(*out) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubServerTLSConfig.
 |  | ||||||
| func (in *GitHubServerTLSConfig) DeepCopy() *GitHubServerTLSConfig { |  | ||||||
| 	if in == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	out := new(GitHubServerTLSConfig) |  | ||||||
| 	in.DeepCopyInto(out) |  | ||||||
| 	return out |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||||
| func (in *HistogramMetric) DeepCopyInto(out *HistogramMetric) { | func (in *HistogramMetric) DeepCopyInto(out *HistogramMetric) { | ||||||
| 	*out = *in | 	*out = *in | ||||||
|  | @ -669,3 +684,48 @@ func (in *TLSCertificateSource) DeepCopy() *TLSCertificateSource { | ||||||
| 	in.DeepCopyInto(out) | 	in.DeepCopyInto(out) | ||||||
| 	return out | 	return out | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||||
|  | func (in *TLSConfig) DeepCopyInto(out *TLSConfig) { | ||||||
|  | 	*out = *in | ||||||
|  | 	if in.CertificateFrom != nil { | ||||||
|  | 		in, out := &in.CertificateFrom, &out.CertificateFrom | ||||||
|  | 		*out = new(TLSCertificateSource) | ||||||
|  | 		(*in).DeepCopyInto(*out) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
 | ||||||
|  | func (in *TLSConfig) DeepCopy() *TLSConfig { | ||||||
|  | 	if in == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	out := new(TLSConfig) | ||||||
|  | 	in.DeepCopyInto(out) | ||||||
|  | 	return out | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||||
|  | func (in *VaultConfig) DeepCopyInto(out *VaultConfig) { | ||||||
|  | 	*out = *in | ||||||
|  | 	if in.AzureKeyVault != nil { | ||||||
|  | 		in, out := &in.AzureKeyVault, &out.AzureKeyVault | ||||||
|  | 		*out = new(AzureKeyVaultConfig) | ||||||
|  | 		**out = **in | ||||||
|  | 	} | ||||||
|  | 	if in.Proxy != nil { | ||||||
|  | 		in, out := &in.Proxy, &out.Proxy | ||||||
|  | 		*out = new(ProxyConfig) | ||||||
|  | 		(*in).DeepCopyInto(*out) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultConfig.
 | ||||||
|  | func (in *VaultConfig) DeepCopy() *VaultConfig { | ||||||
|  | 	if in == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	out := new(VaultConfig) | ||||||
|  | 	in.DeepCopyInto(out) | ||||||
|  | 	return out | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -7863,6 +7863,53 @@ spec: | ||||||
|                         - containers |                         - containers | ||||||
|                       type: object |                       type: object | ||||||
|                   type: object |                   type: object | ||||||
|  |                 vaultConfig: | ||||||
|  |                   properties: | ||||||
|  |                     azureKeyVault: | ||||||
|  |                       properties: | ||||||
|  |                         certificatePath: | ||||||
|  |                           type: string | ||||||
|  |                         clientId: | ||||||
|  |                           type: string | ||||||
|  |                         tenantId: | ||||||
|  |                           type: string | ||||||
|  |                         url: | ||||||
|  |                           type: string | ||||||
|  |                       required: | ||||||
|  |                         - certificatePath | ||||||
|  |                         - clientId | ||||||
|  |                         - tenantId | ||||||
|  |                         - url | ||||||
|  |                       type: object | ||||||
|  |                     proxy: | ||||||
|  |                       properties: | ||||||
|  |                         http: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         https: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         noProxy: | ||||||
|  |                           items: | ||||||
|  |                             type: string | ||||||
|  |                           type: array | ||||||
|  |                       type: object | ||||||
|  |                     type: | ||||||
|  |                       description: |- | ||||||
|  |                         VaultType represents the type of vault that can be used in the application. | ||||||
|  |                         It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                       type: string | ||||||
|  |                   type: object | ||||||
|               type: object |               type: object | ||||||
|             status: |             status: | ||||||
|               description: AutoscalingListenerStatus defines the observed state of AutoscalingListener |               description: AutoscalingListenerStatus defines the observed state of AutoscalingListener | ||||||
|  |  | ||||||
|  | @ -15504,6 +15504,82 @@ spec: | ||||||
|                         - containers |                         - containers | ||||||
|                       type: object |                       type: object | ||||||
|                   type: object |                   type: object | ||||||
|  |                 vaultConfig: | ||||||
|  |                   properties: | ||||||
|  |                     azureKeyVault: | ||||||
|  |                       properties: | ||||||
|  |                         certificatePath: | ||||||
|  |                           type: string | ||||||
|  |                         clientId: | ||||||
|  |                           type: string | ||||||
|  |                         tenantId: | ||||||
|  |                           type: string | ||||||
|  |                         url: | ||||||
|  |                           type: string | ||||||
|  |                       required: | ||||||
|  |                         - certificatePath | ||||||
|  |                         - clientId | ||||||
|  |                         - tenantId | ||||||
|  |                         - url | ||||||
|  |                       type: object | ||||||
|  |                     proxy: | ||||||
|  |                       properties: | ||||||
|  |                         http: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         https: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         noProxy: | ||||||
|  |                           items: | ||||||
|  |                             type: string | ||||||
|  |                           type: array | ||||||
|  |                       type: object | ||||||
|  |                     type: | ||||||
|  |                       description: |- | ||||||
|  |                         VaultType represents the type of vault that can be used in the application. | ||||||
|  |                         It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                       type: string | ||||||
|  |                   type: object | ||||||
|  |                 vaultServerTLS: | ||||||
|  |                   properties: | ||||||
|  |                     certificateFrom: | ||||||
|  |                       description: Required | ||||||
|  |                       properties: | ||||||
|  |                         configMapKeyRef: | ||||||
|  |                           description: Required | ||||||
|  |                           properties: | ||||||
|  |                             key: | ||||||
|  |                               description: The key to select. | ||||||
|  |                               type: string | ||||||
|  |                             name: | ||||||
|  |                               default: "" | ||||||
|  |                               description: |- | ||||||
|  |                                 Name of the referent. | ||||||
|  |                                 This field is effectively required, but due to backwards compatibility is | ||||||
|  |                                 allowed to be empty. Instances of this type with an empty value here are | ||||||
|  |                                 almost certainly wrong. | ||||||
|  |                                 More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names | ||||||
|  |                               type: string | ||||||
|  |                             optional: | ||||||
|  |                               description: Specify whether the ConfigMap or its key must be defined | ||||||
|  |                               type: boolean | ||||||
|  |                           required: | ||||||
|  |                             - key | ||||||
|  |                           type: object | ||||||
|  |                           x-kubernetes-map-type: atomic | ||||||
|  |                       type: object | ||||||
|  |                   type: object | ||||||
|               type: object |               type: object | ||||||
|             status: |             status: | ||||||
|               description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet |               description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet | ||||||
|  |  | ||||||
|  | @ -7784,6 +7784,53 @@ spec: | ||||||
|                   required: |                   required: | ||||||
|                     - containers |                     - containers | ||||||
|                   type: object |                   type: object | ||||||
|  |                 vaultConfig: | ||||||
|  |                   properties: | ||||||
|  |                     azureKeyVault: | ||||||
|  |                       properties: | ||||||
|  |                         certificatePath: | ||||||
|  |                           type: string | ||||||
|  |                         clientId: | ||||||
|  |                           type: string | ||||||
|  |                         tenantId: | ||||||
|  |                           type: string | ||||||
|  |                         url: | ||||||
|  |                           type: string | ||||||
|  |                       required: | ||||||
|  |                         - certificatePath | ||||||
|  |                         - clientId | ||||||
|  |                         - tenantId | ||||||
|  |                         - url | ||||||
|  |                       type: object | ||||||
|  |                     proxy: | ||||||
|  |                       properties: | ||||||
|  |                         http: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         https: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         noProxy: | ||||||
|  |                           items: | ||||||
|  |                             type: string | ||||||
|  |                           type: array | ||||||
|  |                       type: object | ||||||
|  |                     type: | ||||||
|  |                       description: |- | ||||||
|  |                         VaultType represents the type of vault that can be used in the application. | ||||||
|  |                         It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                       type: string | ||||||
|  |                   type: object | ||||||
|               required: |               required: | ||||||
|                 - githubConfigSecret |                 - githubConfigSecret | ||||||
|                 - githubConfigUrl |                 - githubConfigUrl | ||||||
|  |  | ||||||
|  | @ -7778,6 +7778,53 @@ spec: | ||||||
|                       required: |                       required: | ||||||
|                         - containers |                         - containers | ||||||
|                       type: object |                       type: object | ||||||
|  |                     vaultConfig: | ||||||
|  |                       properties: | ||||||
|  |                         azureKeyVault: | ||||||
|  |                           properties: | ||||||
|  |                             certificatePath: | ||||||
|  |                               type: string | ||||||
|  |                             clientId: | ||||||
|  |                               type: string | ||||||
|  |                             tenantId: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               type: string | ||||||
|  |                           required: | ||||||
|  |                             - certificatePath | ||||||
|  |                             - clientId | ||||||
|  |                             - tenantId | ||||||
|  |                             - url | ||||||
|  |                           type: object | ||||||
|  |                         proxy: | ||||||
|  |                           properties: | ||||||
|  |                             http: | ||||||
|  |                               properties: | ||||||
|  |                                 credentialSecretRef: | ||||||
|  |                                   type: string | ||||||
|  |                                 url: | ||||||
|  |                                   description: Required | ||||||
|  |                                   type: string | ||||||
|  |                               type: object | ||||||
|  |                             https: | ||||||
|  |                               properties: | ||||||
|  |                                 credentialSecretRef: | ||||||
|  |                                   type: string | ||||||
|  |                                 url: | ||||||
|  |                                   description: Required | ||||||
|  |                                   type: string | ||||||
|  |                               type: object | ||||||
|  |                             noProxy: | ||||||
|  |                               items: | ||||||
|  |                                 type: string | ||||||
|  |                               type: array | ||||||
|  |                           type: object | ||||||
|  |                         type: | ||||||
|  |                           description: |- | ||||||
|  |                             VaultType represents the type of vault that can be used in the application. | ||||||
|  |                             It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                           type: string | ||||||
|  |                       type: object | ||||||
|                   required: |                   required: | ||||||
|                     - githubConfigSecret |                     - githubConfigSecret | ||||||
|                     - githubConfigUrl |                     - githubConfigUrl | ||||||
|  |  | ||||||
|  | @ -66,6 +66,24 @@ spec: | ||||||
|     {{- end }} |     {{- end }} | ||||||
|   {{- end }} |   {{- end }} | ||||||
| 
 | 
 | ||||||
|  |   {{- if and .Values.keyVault .Values.keyVault.type }} | ||||||
|  |   vaultConfig: | ||||||
|  |     type: {{ .Values.keyVault.type }} | ||||||
|  |     {{- if eq .Values.keyVault.type "azure_key_vault" }} | ||||||
|  |     azureKeyVault: | ||||||
|  |       url: {{ .Values.keyVault.azureKeyVault.url }} | ||||||
|  |       tenantId: {{ .Values.keyVault.azureKeyVault.tenantId }} | ||||||
|  |       clientId: {{ .Values.keyVault.azureKeyVault.clientId }} | ||||||
|  |       certificatePath: {{ .Values.keyVault.azureKeyVault.certificatePath }} | ||||||
|  |       secretKey: {{ .Values.keyVault.azureKeyVault.secretKey }} | ||||||
|  |       {{- if .Values.keyVault.azureKeyVault.proxy }} | ||||||
|  |       proxy: {{- toYaml .Values.keyVault.azureKeyVault.proxy | nindent 6 }} | ||||||
|  |       {{- end }} | ||||||
|  |     {{- else }} | ||||||
|  |     {{- fail "Unsupported vaultConfig type: " .Values.vaultConfig.type }} | ||||||
|  |     {{- end }} | ||||||
|  |   {{- end }} | ||||||
|  | 
 | ||||||
|   {{- if .Values.proxy }} |   {{- if .Values.proxy }} | ||||||
|   proxy: |   proxy: | ||||||
|     {{- if .Values.proxy.http }} |     {{- if .Values.proxy.http }} | ||||||
|  |  | ||||||
|  | @ -1158,7 +1158,7 @@ func TestTemplateRenderedWithTLS(t *testing.T) { | ||||||
| 			ars := render(t, options) | 			ars := render(t, options) | ||||||
| 
 | 
 | ||||||
| 			require.NotNil(t, ars.Spec.GitHubServerTLS) | 			require.NotNil(t, ars.Spec.GitHubServerTLS) | ||||||
| 			expected := &v1alpha1.GitHubServerTLSConfig{ | 			expected := &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1218,7 +1218,7 @@ func TestTemplateRenderedWithTLS(t *testing.T) { | ||||||
| 			ars := render(t, options) | 			ars := render(t, options) | ||||||
| 
 | 
 | ||||||
| 			require.NotNil(t, ars.Spec.GitHubServerTLS) | 			require.NotNil(t, ars.Spec.GitHubServerTLS) | ||||||
| 			expected := &v1alpha1.GitHubServerTLSConfig{ | 			expected := &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1278,7 +1278,7 @@ func TestTemplateRenderedWithTLS(t *testing.T) { | ||||||
| 			ars := render(t, options) | 			ars := render(t, options) | ||||||
| 
 | 
 | ||||||
| 			require.NotNil(t, ars.Spec.GitHubServerTLS) | 			require.NotNil(t, ars.Spec.GitHubServerTLS) | ||||||
| 			expected := &v1alpha1.GitHubServerTLSConfig{ | 			expected := &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1338,7 +1338,7 @@ func TestTemplateRenderedWithTLS(t *testing.T) { | ||||||
| 			ars := render(t, options) | 			ars := render(t, options) | ||||||
| 
 | 
 | ||||||
| 			require.NotNil(t, ars.Spec.GitHubServerTLS) | 			require.NotNil(t, ars.Spec.GitHubServerTLS) | ||||||
| 			expected := &v1alpha1.GitHubServerTLSConfig{ | 			expected := &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1394,7 +1394,7 @@ func TestTemplateRenderedWithTLS(t *testing.T) { | ||||||
| 			ars := render(t, options) | 			ars := render(t, options) | ||||||
| 
 | 
 | ||||||
| 			require.NotNil(t, ars.Spec.GitHubServerTLS) | 			require.NotNil(t, ars.Spec.GitHubServerTLS) | ||||||
| 			expected := &v1alpha1.GitHubServerTLSConfig{ | 			expected := &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1450,7 +1450,7 @@ func TestTemplateRenderedWithTLS(t *testing.T) { | ||||||
| 			ars := render(t, options) | 			ars := render(t, options) | ||||||
| 
 | 
 | ||||||
| 			require.NotNil(t, ars.Spec.GitHubServerTLS) | 			require.NotNil(t, ars.Spec.GitHubServerTLS) | ||||||
| 			expected := &v1alpha1.GitHubServerTLSConfig{ | 			expected := &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  |  | ||||||
|  | @ -88,6 +88,27 @@ githubConfigSecret: | ||||||
| #       key: ca.crt | #       key: ca.crt | ||||||
| #   runnerMountPath: /usr/local/share/ca-certificates/ | #   runnerMountPath: /usr/local/share/ca-certificates/ | ||||||
| 
 | 
 | ||||||
|  | # keyVault: | ||||||
|  |   # Available values: "azure_key_vault" | ||||||
|  |   # type: "" | ||||||
|  |   # Configuration related to azure key vault | ||||||
|  |   # azure_key_vault: | ||||||
|  |   #   url: "" | ||||||
|  |   #   client_id: "" | ||||||
|  |   #   tenant_id: "" | ||||||
|  |   #   certificate_path: "" | ||||||
|  |     # proxy: | ||||||
|  |     #   http: | ||||||
|  |     #     url: http://proxy.com:1234 | ||||||
|  |     #     credentialSecretRef: proxy-auth # a secret with `username` and `password` keys | ||||||
|  |     #   https: | ||||||
|  |     #     url: http://proxy.com:1234 | ||||||
|  |     #     credentialSecretRef: proxy-auth # a secret with `username` and `password` keys | ||||||
|  |     #   noProxy: | ||||||
|  |     #     - example.com | ||||||
|  |     #     - example.org | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ## Container mode is an object that provides out-of-box configuration | ## Container mode is an object that provides out-of-box configuration | ||||||
| ## for dind and kubernetes mode. Template will be modified as documented under the | ## for dind and kubernetes mode. Template will be modified as documented under the | ||||||
| ## template object. | ## template object. | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ import ( | ||||||
| 	"github.com/actions/actions-runner-controller/github/actions" | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
| 	"github.com/actions/actions-runner-controller/logging" | 	"github.com/actions/actions-runner-controller/logging" | ||||||
| 	"github.com/actions/actions-runner-controller/vault" | 	"github.com/actions/actions-runner-controller/vault" | ||||||
|  | 	"github.com/actions/actions-runner-controller/vault/azurekeyvault" | ||||||
| 	"github.com/go-logr/logr" | 	"github.com/go-logr/logr" | ||||||
| 	"golang.org/x/net/http/httpproxy" | 	"golang.org/x/net/http/httpproxy" | ||||||
| ) | ) | ||||||
|  | @ -23,6 +24,8 @@ type Config struct { | ||||||
| 	ConfigureUrl   string          `json:"configure_url"` | 	ConfigureUrl   string          `json:"configure_url"` | ||||||
| 	VaultType      vault.VaultType `json:"vault_type"` | 	VaultType      vault.VaultType `json:"vault_type"` | ||||||
| 	VaultLookupKey string          `json:"vault_lookup_key"` | 	VaultLookupKey string          `json:"vault_lookup_key"` | ||||||
|  | 	// If the VaultType is set to "azure_key_vault", this field must be populated.
 | ||||||
|  | 	AzureKeyVaultConfig *azurekeyvault.Config `json:"azure_key_vault,omitempty"` | ||||||
| 	// AppConfig contains the GitHub App configuration.
 | 	// AppConfig contains the GitHub App configuration.
 | ||||||
| 	// It is initially set to nil if VaultType is set.
 | 	// It is initially set to nil if VaultType is set.
 | ||||||
| 	// Otherwise, it is populated with the GitHub App credentials from the GitHub secret.
 | 	// Otherwise, it is populated with the GitHub App credentials from the GitHub secret.
 | ||||||
|  | @ -53,31 +56,28 @@ func Read(ctx context.Context, configPath string) (*Config, error) { | ||||||
| 		return nil, fmt.Errorf("failed to decode config: %w", err) | 		return nil, fmt.Errorf("failed to decode config: %w", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if config.VaultType == "" { | 	var vault vault.Vault | ||||||
|  | 	switch config.VaultType { | ||||||
|  | 	case "": | ||||||
| 		if err := config.Validate(); err != nil { | 		if err := config.Validate(); err != nil { | ||||||
| 			return nil, fmt.Errorf("failed to validate configuration: %v", err) | 			return nil, fmt.Errorf("failed to validate configuration: %v", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return &config, nil | 		return &config, nil | ||||||
| 	} | 	case "azure_key_vault": | ||||||
| 
 | 		akv, err := azurekeyvault.New(*config.AzureKeyVaultConfig) | ||||||
| 	if config.VaultLookupKey == "" { |  | ||||||
| 		panic(fmt.Errorf("vault type set to %q, but lookup key is empty", config.VaultType)) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	vaults, err := vault.InitAll("LISTENER_") |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 		return nil, fmt.Errorf("failed to initialize vaults: %v", err) | 			return nil, fmt.Errorf("failed to create Azure Key Vault client: %w", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	vault, ok := vaults[config.VaultType] | 		vault = akv | ||||||
| 	if !ok { | 	default: | ||||||
| 		return nil, fmt.Errorf("vault %q is not initialized", config.VaultType) | 		return nil, fmt.Errorf("unsupported vault type: %s", config.VaultType) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	appConfigRaw, err := vault.GetSecret(ctx, config.VaultLookupKey) | 	appConfigRaw, err := vault.GetSecret(ctx, config.VaultLookupKey) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, fmt.Errorf("failed to get app config from vault: %w", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	appConfig, err := appconfig.FromString(appConfigRaw) | 	appConfig, err := appconfig.FromString(appConfigRaw) | ||||||
|  |  | ||||||
|  | @ -7863,6 +7863,53 @@ spec: | ||||||
|                         - containers |                         - containers | ||||||
|                       type: object |                       type: object | ||||||
|                   type: object |                   type: object | ||||||
|  |                 vaultConfig: | ||||||
|  |                   properties: | ||||||
|  |                     azureKeyVault: | ||||||
|  |                       properties: | ||||||
|  |                         certificatePath: | ||||||
|  |                           type: string | ||||||
|  |                         clientId: | ||||||
|  |                           type: string | ||||||
|  |                         tenantId: | ||||||
|  |                           type: string | ||||||
|  |                         url: | ||||||
|  |                           type: string | ||||||
|  |                       required: | ||||||
|  |                         - certificatePath | ||||||
|  |                         - clientId | ||||||
|  |                         - tenantId | ||||||
|  |                         - url | ||||||
|  |                       type: object | ||||||
|  |                     proxy: | ||||||
|  |                       properties: | ||||||
|  |                         http: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         https: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         noProxy: | ||||||
|  |                           items: | ||||||
|  |                             type: string | ||||||
|  |                           type: array | ||||||
|  |                       type: object | ||||||
|  |                     type: | ||||||
|  |                       description: |- | ||||||
|  |                         VaultType represents the type of vault that can be used in the application. | ||||||
|  |                         It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                       type: string | ||||||
|  |                   type: object | ||||||
|               type: object |               type: object | ||||||
|             status: |             status: | ||||||
|               description: AutoscalingListenerStatus defines the observed state of AutoscalingListener |               description: AutoscalingListenerStatus defines the observed state of AutoscalingListener | ||||||
|  |  | ||||||
|  | @ -15504,6 +15504,82 @@ spec: | ||||||
|                         - containers |                         - containers | ||||||
|                       type: object |                       type: object | ||||||
|                   type: object |                   type: object | ||||||
|  |                 vaultConfig: | ||||||
|  |                   properties: | ||||||
|  |                     azureKeyVault: | ||||||
|  |                       properties: | ||||||
|  |                         certificatePath: | ||||||
|  |                           type: string | ||||||
|  |                         clientId: | ||||||
|  |                           type: string | ||||||
|  |                         tenantId: | ||||||
|  |                           type: string | ||||||
|  |                         url: | ||||||
|  |                           type: string | ||||||
|  |                       required: | ||||||
|  |                         - certificatePath | ||||||
|  |                         - clientId | ||||||
|  |                         - tenantId | ||||||
|  |                         - url | ||||||
|  |                       type: object | ||||||
|  |                     proxy: | ||||||
|  |                       properties: | ||||||
|  |                         http: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         https: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         noProxy: | ||||||
|  |                           items: | ||||||
|  |                             type: string | ||||||
|  |                           type: array | ||||||
|  |                       type: object | ||||||
|  |                     type: | ||||||
|  |                       description: |- | ||||||
|  |                         VaultType represents the type of vault that can be used in the application. | ||||||
|  |                         It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                       type: string | ||||||
|  |                   type: object | ||||||
|  |                 vaultServerTLS: | ||||||
|  |                   properties: | ||||||
|  |                     certificateFrom: | ||||||
|  |                       description: Required | ||||||
|  |                       properties: | ||||||
|  |                         configMapKeyRef: | ||||||
|  |                           description: Required | ||||||
|  |                           properties: | ||||||
|  |                             key: | ||||||
|  |                               description: The key to select. | ||||||
|  |                               type: string | ||||||
|  |                             name: | ||||||
|  |                               default: "" | ||||||
|  |                               description: |- | ||||||
|  |                                 Name of the referent. | ||||||
|  |                                 This field is effectively required, but due to backwards compatibility is | ||||||
|  |                                 allowed to be empty. Instances of this type with an empty value here are | ||||||
|  |                                 almost certainly wrong. | ||||||
|  |                                 More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names | ||||||
|  |                               type: string | ||||||
|  |                             optional: | ||||||
|  |                               description: Specify whether the ConfigMap or its key must be defined | ||||||
|  |                               type: boolean | ||||||
|  |                           required: | ||||||
|  |                             - key | ||||||
|  |                           type: object | ||||||
|  |                           x-kubernetes-map-type: atomic | ||||||
|  |                       type: object | ||||||
|  |                   type: object | ||||||
|               type: object |               type: object | ||||||
|             status: |             status: | ||||||
|               description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet |               description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet | ||||||
|  |  | ||||||
|  | @ -7784,6 +7784,53 @@ spec: | ||||||
|                   required: |                   required: | ||||||
|                     - containers |                     - containers | ||||||
|                   type: object |                   type: object | ||||||
|  |                 vaultConfig: | ||||||
|  |                   properties: | ||||||
|  |                     azureKeyVault: | ||||||
|  |                       properties: | ||||||
|  |                         certificatePath: | ||||||
|  |                           type: string | ||||||
|  |                         clientId: | ||||||
|  |                           type: string | ||||||
|  |                         tenantId: | ||||||
|  |                           type: string | ||||||
|  |                         url: | ||||||
|  |                           type: string | ||||||
|  |                       required: | ||||||
|  |                         - certificatePath | ||||||
|  |                         - clientId | ||||||
|  |                         - tenantId | ||||||
|  |                         - url | ||||||
|  |                       type: object | ||||||
|  |                     proxy: | ||||||
|  |                       properties: | ||||||
|  |                         http: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         https: | ||||||
|  |                           properties: | ||||||
|  |                             credentialSecretRef: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               description: Required | ||||||
|  |                               type: string | ||||||
|  |                           type: object | ||||||
|  |                         noProxy: | ||||||
|  |                           items: | ||||||
|  |                             type: string | ||||||
|  |                           type: array | ||||||
|  |                       type: object | ||||||
|  |                     type: | ||||||
|  |                       description: |- | ||||||
|  |                         VaultType represents the type of vault that can be used in the application. | ||||||
|  |                         It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                       type: string | ||||||
|  |                   type: object | ||||||
|               required: |               required: | ||||||
|                 - githubConfigSecret |                 - githubConfigSecret | ||||||
|                 - githubConfigUrl |                 - githubConfigUrl | ||||||
|  |  | ||||||
|  | @ -7778,6 +7778,53 @@ spec: | ||||||
|                       required: |                       required: | ||||||
|                         - containers |                         - containers | ||||||
|                       type: object |                       type: object | ||||||
|  |                     vaultConfig: | ||||||
|  |                       properties: | ||||||
|  |                         azureKeyVault: | ||||||
|  |                           properties: | ||||||
|  |                             certificatePath: | ||||||
|  |                               type: string | ||||||
|  |                             clientId: | ||||||
|  |                               type: string | ||||||
|  |                             tenantId: | ||||||
|  |                               type: string | ||||||
|  |                             url: | ||||||
|  |                               type: string | ||||||
|  |                           required: | ||||||
|  |                             - certificatePath | ||||||
|  |                             - clientId | ||||||
|  |                             - tenantId | ||||||
|  |                             - url | ||||||
|  |                           type: object | ||||||
|  |                         proxy: | ||||||
|  |                           properties: | ||||||
|  |                             http: | ||||||
|  |                               properties: | ||||||
|  |                                 credentialSecretRef: | ||||||
|  |                                   type: string | ||||||
|  |                                 url: | ||||||
|  |                                   description: Required | ||||||
|  |                                   type: string | ||||||
|  |                               type: object | ||||||
|  |                             https: | ||||||
|  |                               properties: | ||||||
|  |                                 credentialSecretRef: | ||||||
|  |                                   type: string | ||||||
|  |                                 url: | ||||||
|  |                                   description: Required | ||||||
|  |                                   type: string | ||||||
|  |                               type: object | ||||||
|  |                             noProxy: | ||||||
|  |                               items: | ||||||
|  |                                 type: string | ||||||
|  |                               type: array | ||||||
|  |                           type: object | ||||||
|  |                         type: | ||||||
|  |                           description: |- | ||||||
|  |                             VaultType represents the type of vault that can be used in the application. | ||||||
|  |                             It is used to identify which vault integration should be used to resolve secrets. | ||||||
|  |                           type: string | ||||||
|  |                       type: object | ||||||
|                   required: |                   required: | ||||||
|                     - githubConfigSecret |                     - githubConfigSecret | ||||||
|                     - githubConfigUrl |                     - githubConfigUrl | ||||||
|  |  | ||||||
|  | @ -1065,7 +1065,7 @@ var _ = Describe("Test GitHub Server TLS configuration", func() { | ||||||
| 			Spec: v1alpha1.AutoscalingRunnerSetSpec{ | 			Spec: v1alpha1.AutoscalingRunnerSetSpec{ | ||||||
| 				GitHubConfigUrl:    "https://github.com/owner/repo", | 				GitHubConfigUrl:    "https://github.com/owner/repo", | ||||||
| 				GitHubConfigSecret: configSecret.Name, | 				GitHubConfigSecret: configSecret.Name, | ||||||
| 				GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{ | 				GitHubServerTLS: &v1alpha1.TLSConfig{ | ||||||
| 					CertificateFrom: &v1alpha1.TLSCertificateSource{ | 					CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 						ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 						ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 							LocalObjectReference: corev1.LocalObjectReference{ | 							LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1101,7 +1101,7 @@ var _ = Describe("Test GitHub Server TLS configuration", func() { | ||||||
| 			Spec: v1alpha1.AutoscalingListenerSpec{ | 			Spec: v1alpha1.AutoscalingListenerSpec{ | ||||||
| 				GitHubConfigUrl:    "https://github.com/owner/repo", | 				GitHubConfigUrl:    "https://github.com/owner/repo", | ||||||
| 				GitHubConfigSecret: configSecret.Name, | 				GitHubConfigSecret: configSecret.Name, | ||||||
| 				GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{ | 				GitHubServerTLS: &v1alpha1.TLSConfig{ | ||||||
| 					CertificateFrom: &v1alpha1.TLSCertificateSource{ | 					CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 						ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 						ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 							LocalObjectReference: corev1.LocalObjectReference{ | 							LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  |  | ||||||
|  | @ -1201,7 +1201,7 @@ var _ = Describe("Test client optional configuration", Ordered, func() { | ||||||
| 				Spec: v1alpha1.AutoscalingRunnerSetSpec{ | 				Spec: v1alpha1.AutoscalingRunnerSetSpec{ | ||||||
| 					GitHubConfigUrl:    server.ConfigURLForOrg("my-org"), | 					GitHubConfigUrl:    server.ConfigURLForOrg("my-org"), | ||||||
| 					GitHubConfigSecret: configSecret.Name, | 					GitHubConfigSecret: configSecret.Name, | ||||||
| 					GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{ | 					GitHubServerTLS: &v1alpha1.TLSConfig{ | ||||||
| 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 								LocalObjectReference: corev1.LocalObjectReference{ | 								LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1254,7 +1254,7 @@ var _ = Describe("Test client optional configuration", Ordered, func() { | ||||||
| 				Spec: v1alpha1.AutoscalingRunnerSetSpec{ | 				Spec: v1alpha1.AutoscalingRunnerSetSpec{ | ||||||
| 					GitHubConfigUrl:    "https://github.com/owner/repo", | 					GitHubConfigUrl:    "https://github.com/owner/repo", | ||||||
| 					GitHubConfigSecret: configSecret.Name, | 					GitHubConfigSecret: configSecret.Name, | ||||||
| 					GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{ | 					GitHubServerTLS: &v1alpha1.TLSConfig{ | ||||||
| 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 								LocalObjectReference: corev1.LocalObjectReference{ | 								LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  | @ -1318,7 +1318,7 @@ var _ = Describe("Test client optional configuration", Ordered, func() { | ||||||
| 				Spec: v1alpha1.AutoscalingRunnerSetSpec{ | 				Spec: v1alpha1.AutoscalingRunnerSetSpec{ | ||||||
| 					GitHubConfigUrl:    "https://github.com/owner/repo", | 					GitHubConfigUrl:    "https://github.com/owner/repo", | ||||||
| 					GitHubConfigSecret: configSecret.Name, | 					GitHubConfigSecret: configSecret.Name, | ||||||
| 					GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{ | 					GitHubServerTLS: &v1alpha1.TLSConfig{ | ||||||
| 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 								LocalObjectReference: corev1.LocalObjectReference{ | 								LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  |  | ||||||
|  | @ -43,8 +43,6 @@ const ( | ||||||
| 	AnnotationKeyGitHubRunnerGroupName    = "actions.github.com/runner-group-name" | 	AnnotationKeyGitHubRunnerGroupName    = "actions.github.com/runner-group-name" | ||||||
| 	AnnotationKeyGitHubRunnerScaleSetName = "actions.github.com/runner-scale-set-name" | 	AnnotationKeyGitHubRunnerScaleSetName = "actions.github.com/runner-scale-set-name" | ||||||
| 	AnnotationKeyPatchID                  = "actions.github.com/patch-id" | 	AnnotationKeyPatchID                  = "actions.github.com/patch-id" | ||||||
| 
 |  | ||||||
| 	AnnotationKeyGitHubVaultType = "actions.github.com/vault" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Labels applied to listener roles
 | // Labels applied to listener roles
 | ||||||
|  |  | ||||||
|  | @ -1093,7 +1093,7 @@ var _ = Describe("EphemeralRunner", func() { | ||||||
| 
 | 
 | ||||||
| 			ephemeralRunner := newExampleRunner("test-runner", autoScalingNS.Name, configSecret.Name) | 			ephemeralRunner := newExampleRunner("test-runner", autoScalingNS.Name, configSecret.Name) | ||||||
| 			ephemeralRunner.Spec.GitHubConfigUrl = server.ConfigURLForOrg("my-org") | 			ephemeralRunner.Spec.GitHubConfigUrl = server.ConfigURLForOrg("my-org") | ||||||
| 			ephemeralRunner.Spec.GitHubServerTLS = &v1alpha1.GitHubServerTLSConfig{ | 			ephemeralRunner.Spec.GitHubServerTLS = &v1alpha1.TLSConfig{ | ||||||
| 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | 				CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 					ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 						LocalObjectReference: corev1.LocalObjectReference{ | 						LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  |  | ||||||
|  | @ -1460,7 +1460,7 @@ var _ = Describe("Test EphemeralRunnerSet controller with custom root CA", func( | ||||||
| 				EphemeralRunnerSpec: v1alpha1.EphemeralRunnerSpec{ | 				EphemeralRunnerSpec: v1alpha1.EphemeralRunnerSpec{ | ||||||
| 					GitHubConfigUrl:    server.ConfigURLForOrg("my-org"), | 					GitHubConfigUrl:    server.ConfigURLForOrg("my-org"), | ||||||
| 					GitHubConfigSecret: configSecret.Name, | 					GitHubConfigSecret: configSecret.Name, | ||||||
| 					GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{ | 					GitHubServerTLS: &v1alpha1.TLSConfig{ | ||||||
| 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | 						CertificateFrom: &v1alpha1.TLSCertificateSource{ | ||||||
| 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | 							ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ | ||||||
| 								LocalObjectReference: corev1.LocalObjectReference{ | 								LocalObjectReference: corev1.LocalObjectReference{ | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ import ( | ||||||
| 	"github.com/actions/actions-runner-controller/github/actions" | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
| 	"github.com/actions/actions-runner-controller/hash" | 	"github.com/actions/actions-runner-controller/hash" | ||||||
| 	"github.com/actions/actions-runner-controller/logging" | 	"github.com/actions/actions-runner-controller/logging" | ||||||
| 	"github.com/actions/actions-runner-controller/vault" | 	"github.com/actions/actions-runner-controller/vault/azurekeyvault" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	rbacv1 "k8s.io/api/rbac/v1" | 	rbacv1 "k8s.io/api/rbac/v1" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | @ -110,10 +110,6 @@ func (b *ResourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1. | ||||||
| 		annotationKeyValuesHash:     autoscalingRunnerSet.Annotations[annotationKeyValuesHash], | 		annotationKeyValuesHash:     autoscalingRunnerSet.Annotations[annotationKeyValuesHash], | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if v, ok := autoscalingRunnerSet.Annotations[AnnotationKeyGitHubVaultType]; ok { |  | ||||||
| 		annotations[AnnotationKeyGitHubVaultType] = v |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := applyGitHubURLLabels(autoscalingRunnerSet.Spec.GitHubConfigUrl, labels); err != nil { | 	if err := applyGitHubURLLabels(autoscalingRunnerSet.Spec.GitHubConfigUrl, labels); err != nil { | ||||||
| 		return nil, fmt.Errorf("failed to apply GitHub URL labels: %v", err) | 		return nil, fmt.Errorf("failed to apply GitHub URL labels: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -128,6 +124,7 @@ func (b *ResourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1. | ||||||
| 		Spec: v1alpha1.AutoscalingListenerSpec{ | 		Spec: v1alpha1.AutoscalingListenerSpec{ | ||||||
| 			GitHubConfigUrl:               autoscalingRunnerSet.Spec.GitHubConfigUrl, | 			GitHubConfigUrl:               autoscalingRunnerSet.Spec.GitHubConfigUrl, | ||||||
| 			GitHubConfigSecret:            autoscalingRunnerSet.Spec.GitHubConfigSecret, | 			GitHubConfigSecret:            autoscalingRunnerSet.Spec.GitHubConfigSecret, | ||||||
|  | 			VaultConfig:                   autoscalingRunnerSet.VaultConfig(), | ||||||
| 			RunnerScaleSetId:              runnerScaleSetId, | 			RunnerScaleSetId:              runnerScaleSetId, | ||||||
| 			AutoscalingRunnerSetNamespace: autoscalingRunnerSet.Namespace, | 			AutoscalingRunnerSetNamespace: autoscalingRunnerSet.Namespace, | ||||||
| 			AutoscalingRunnerSetName:      autoscalingRunnerSet.Name, | 			AutoscalingRunnerSetName:      autoscalingRunnerSet.Name, | ||||||
|  | @ -193,15 +190,18 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha | ||||||
| 		Metrics:                     autoscalingListener.Spec.Metrics, | 		Metrics:                     autoscalingListener.Spec.Metrics, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if ty, ok := autoscalingListener.Annotations[AnnotationKeyGitHubVaultType]; !ok { | 	vault := autoscalingListener.Spec.VaultConfig | ||||||
|  | 	if vault == nil { | ||||||
| 		config.AppConfig = appConfig | 		config.AppConfig = appConfig | ||||||
| 	} else { | 	} else { | ||||||
| 		vaultType := vault.VaultType(ty) | 		config.VaultType = vault.Type | ||||||
| 		if err := vaultType.Validate(); err != nil { |  | ||||||
| 			return nil, fmt.Errorf("vault type validation error: %w", err) |  | ||||||
| 		} |  | ||||||
| 		config.VaultType = vaultType |  | ||||||
| 		config.VaultLookupKey = autoscalingListener.Spec.GitHubConfigSecret | 		config.VaultLookupKey = autoscalingListener.Spec.GitHubConfigSecret | ||||||
|  | 		config.AzureKeyVaultConfig = &azurekeyvault.Config{ | ||||||
|  | 			TenantID:        vault.AzureKeyVault.TenantID, | ||||||
|  | 			ClientID:        vault.AzureKeyVault.ClientID, | ||||||
|  | 			URL:             vault.AzureKeyVault.URL, | ||||||
|  | 			CertificatePath: vault.AzureKeyVault.CertificatePath, | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err := config.Validate(); err != nil { | 	if err := config.Validate(); err != nil { | ||||||
|  | @ -520,10 +520,6 @@ func (b *ResourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A | ||||||
| 		annotationKeyRunnerSpecHash:           runnerSpecHash, | 		annotationKeyRunnerSpecHash:           runnerSpecHash, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if v, ok := autoscalingRunnerSet.Annotations[AnnotationKeyGitHubVaultType]; ok { |  | ||||||
| 		newAnnotations[AnnotationKeyGitHubVaultType] = v |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{ | 	newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{ | ||||||
| 		TypeMeta: metav1.TypeMeta{}, | 		TypeMeta: metav1.TypeMeta{}, | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | @ -551,6 +547,7 @@ func (b *ResourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A | ||||||
| 				Proxy:              autoscalingRunnerSet.Spec.Proxy, | 				Proxy:              autoscalingRunnerSet.Spec.Proxy, | ||||||
| 				GitHubServerTLS:    autoscalingRunnerSet.Spec.GitHubServerTLS, | 				GitHubServerTLS:    autoscalingRunnerSet.Spec.GitHubServerTLS, | ||||||
| 				PodTemplateSpec:    autoscalingRunnerSet.Spec.Template, | 				PodTemplateSpec:    autoscalingRunnerSet.Spec.Template, | ||||||
|  | 				VaultConfig:        autoscalingRunnerSet.VaultConfig(), | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import ( | ||||||
| 	"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1/appconfig" | 	"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1/appconfig" | ||||||
| 	"github.com/actions/actions-runner-controller/github/actions" | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
| 	"github.com/actions/actions-runner-controller/vault" | 	"github.com/actions/actions-runner-controller/vault" | ||||||
|  | 	"github.com/actions/actions-runner-controller/vault/azurekeyvault" | ||||||
| 	"golang.org/x/net/http/httpproxy" | 	"golang.org/x/net/http/httpproxy" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/types" | 	"k8s.io/apimachinery/pkg/types" | ||||||
|  | @ -20,18 +21,11 @@ import ( | ||||||
| 
 | 
 | ||||||
| type SecretResolver struct { | type SecretResolver struct { | ||||||
| 	k8sClient   client.Client | 	k8sClient   client.Client | ||||||
| 	vaultResolvers map[vault.VaultType]resolver |  | ||||||
| 	multiClient actions.MultiClient | 	multiClient actions.MultiClient | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type SecretResolverOption func(*SecretResolver) | type SecretResolverOption func(*SecretResolver) | ||||||
| 
 | 
 | ||||||
| func WithVault(ty vault.VaultType, vault vault.Vault) SecretResolverOption { |  | ||||||
| 	return func(pool *SecretResolver) { |  | ||||||
| 		pool.vaultResolvers[ty] = &vaultResolver{vault} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func NewSecretResolver(k8sClient client.Client, multiClient actions.MultiClient, opts ...SecretResolverOption) *SecretResolver { | func NewSecretResolver(k8sClient client.Client, multiClient actions.MultiClient, opts ...SecretResolverOption) *SecretResolver { | ||||||
| 	if k8sClient == nil { | 	if k8sClient == nil { | ||||||
| 		panic("k8sClient must not be nil") | 		panic("k8sClient must not be nil") | ||||||
|  | @ -40,7 +34,6 @@ func NewSecretResolver(k8sClient client.Client, multiClient actions.MultiClient, | ||||||
| 	secretResolver := &SecretResolver{ | 	secretResolver := &SecretResolver{ | ||||||
| 		k8sClient:   k8sClient, | 		k8sClient:   k8sClient, | ||||||
| 		multiClient: multiClient, | 		multiClient: multiClient, | ||||||
| 		vaultResolvers: make(map[vault.VaultType]resolver), |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, opt := range opts { | 	for _, opt := range opts { | ||||||
|  | @ -55,7 +48,8 @@ type ActionsGitHubObject interface { | ||||||
| 	GitHubConfigUrl() string | 	GitHubConfigUrl() string | ||||||
| 	GitHubConfigSecret() string | 	GitHubConfigSecret() string | ||||||
| 	Proxy() *v1alpha1.ProxyConfig | 	Proxy() *v1alpha1.ProxyConfig | ||||||
| 	GitHubServerTLS() *v1alpha1.GitHubServerTLSConfig | 	GitHubServerTLS() *v1alpha1.TLSConfig | ||||||
|  | 	VaultConfig() *v1alpha1.VaultConfig | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (sr *SecretResolver) GetAppConfig(ctx context.Context, obj ActionsGitHubObject) (*appconfig.AppConfig, error) { | func (sr *SecretResolver) GetAppConfig(ctx context.Context, obj ActionsGitHubObject) (*appconfig.AppConfig, error) { | ||||||
|  | @ -163,25 +157,32 @@ func (sr *SecretResolver) GetActionsService(ctx context.Context, obj ActionsGitH | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (sr *SecretResolver) resolverForObject(obj ActionsGitHubObject) (resolver, error) { | func (sr *SecretResolver) resolverForObject(obj ActionsGitHubObject) (resolver, error) { | ||||||
| 	ty, ok := obj.GetAnnotations()[AnnotationKeyGitHubVaultType] | 	vaultConfig := obj.VaultConfig() | ||||||
| 	if !ok { | 	if vaultConfig == nil || vaultConfig.Type == "" { | ||||||
| 		return &k8sResolver{ | 		return &k8sResolver{ | ||||||
| 			namespace: obj.GetNamespace(), | 			namespace: obj.GetNamespace(), | ||||||
| 			client:    sr.k8sClient, | 			client:    sr.k8sClient, | ||||||
| 		}, nil | 		}, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	vaultType := vault.VaultType(ty) | 	switch vaultConfig.Type { | ||||||
| 	if err := vaultType.Validate(); err != nil { | 	case vault.VaultTypeAzureKeyVault: | ||||||
| 		return nil, fmt.Errorf("invalid vault type %q: %v", ty, err) | 		akv, err := azurekeyvault.New(azurekeyvault.Config{ | ||||||
|  | 			TenantID:        vaultConfig.AzureKeyVault.TenantID, | ||||||
|  | 			ClientID:        vaultConfig.AzureKeyVault.ClientID, | ||||||
|  | 			URL:             vaultConfig.AzureKeyVault.URL, | ||||||
|  | 			CertificatePath: vaultConfig.AzureKeyVault.CertificatePath, | ||||||
|  | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, fmt.Errorf("failed to create Azure Key Vault client: %v", err) | ||||||
| 		} | 		} | ||||||
|  | 		return &vaultResolver{ | ||||||
|  | 			vault: akv, | ||||||
|  | 		}, nil | ||||||
| 
 | 
 | ||||||
| 	vault, ok := sr.vaultResolvers[vaultType] | 	default: | ||||||
| 	if !ok { | 		return nil, fmt.Errorf("unknown vault type %q", vaultConfig.Type) | ||||||
| 		return nil, fmt.Errorf("unknown vault resolver %q", ty) |  | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	return vault, nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type resolver interface { | type resolver interface { | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								main.go
								
								
								
								
							
							
						
						
									
										13
									
								
								main.go
								
								
								
								
							|  | @ -32,7 +32,6 @@ import ( | ||||||
| 	"github.com/actions/actions-runner-controller/github" | 	"github.com/actions/actions-runner-controller/github" | ||||||
| 	"github.com/actions/actions-runner-controller/github/actions" | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
| 	"github.com/actions/actions-runner-controller/logging" | 	"github.com/actions/actions-runner-controller/logging" | ||||||
| 	"github.com/actions/actions-runner-controller/vault" |  | ||||||
| 	"github.com/kelseyhightower/envconfig" | 	"github.com/kelseyhightower/envconfig" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/runtime" | 	"k8s.io/apimachinery/pkg/runtime" | ||||||
|  | @ -275,21 +274,9 @@ func main() { | ||||||
| 			log.WithName("actions-clients"), | 			log.WithName("actions-clients"), | ||||||
| 		) | 		) | ||||||
| 
 | 
 | ||||||
| 		vaults, err := vault.InitAll("CONTROLLER_MANAGER_") |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Error(err, "unable to read vaults") |  | ||||||
| 			os.Exit(1) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		var secretResolverOptions []actionsgithubcom.SecretResolverOption |  | ||||||
| 		for name, vault := range vaults { |  | ||||||
| 			secretResolverOptions = append(secretResolverOptions, actionsgithubcom.WithVault(name, vault)) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		secretResolver := actionsgithubcom.NewSecretResolver( | 		secretResolver := actionsgithubcom.NewSecretResolver( | ||||||
| 			mgr.GetClient(), | 			mgr.GetClient(), | ||||||
| 			actionsMultiClient, | 			actionsMultiClient, | ||||||
| 			secretResolverOptions..., |  | ||||||
| 		) | 		) | ||||||
| 
 | 
 | ||||||
| 		rb := actionsgithubcom.ResourceBuilder{ | 		rb := actionsgithubcom.ResourceBuilder{ | ||||||
|  |  | ||||||
|  | @ -3,10 +3,8 @@ package azurekeyvault | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets" | 	"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets" | ||||||
| 	"github.com/actions/actions-runner-controller/proxyconfig" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // AzureKeyVault is a struct that holds the Azure Key Vault client.
 | // AzureKeyVault is a struct that holds the Azure Key Vault client.
 | ||||||
|  | @ -27,31 +25,6 @@ func New(cfg Config) (*AzureKeyVault, error) { | ||||||
| 	return &AzureKeyVault{client: client}, nil | 	return &AzureKeyVault{client: client}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FromEnv creates a new AzureKeyVault instance from environment variables.
 |  | ||||||
| // The environment variables should be prefixed with the provided prefix.
 |  | ||||||
| // For example, if the prefix is "AZURE_KEY_VAULT_", the environment variables should be:
 |  | ||||||
| // AZURE_KEY_VAULT_TENANT_ID, AZURE_KEY_VAULT_CLIENT_ID, AZURE_KEY_VAULT_URL,
 |  | ||||||
| // AZURE_KEY_VAULT_CERT_PATH, AZURE_KEY_VAULT_CERT_PASSWORD.
 |  | ||||||
| // The proxy configuration can be set using the environment variables prefixed with "PROXY_".
 |  | ||||||
| // For example, AZURE_KEY_VAULT_PROXY_HTTP_URL, AZURE_KEY_VAULT_PROXY_HTTP_USERNAME, etc.
 |  | ||||||
| func FromEnv(prefix string) (*AzureKeyVault, error) { |  | ||||||
| 	cfg := Config{ |  | ||||||
| 		TenantID:     os.Getenv(prefix + "TENANT_ID"), |  | ||||||
| 		ClientID:     os.Getenv(prefix + "CLIENT_ID"), |  | ||||||
| 		URL:          os.Getenv(prefix + "URL"), |  | ||||||
| 		CertPath:     os.Getenv(prefix + "CERT_PATH"), |  | ||||||
| 		CertPassword: os.Getenv(prefix + "CERT_PASSWORD"), |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	proxyConfig, err := proxyconfig.ReadFromEnv(prefix + "PROXY_") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to read proxy config: %v", err) |  | ||||||
| 	} |  | ||||||
| 	cfg.Proxy = proxyConfig |  | ||||||
| 
 |  | ||||||
| 	return New(cfg) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetSecret retrieves a secret from Azure Key Vault.
 | // GetSecret retrieves a secret from Azure Key Vault.
 | ||||||
| func (v *AzureKeyVault) GetSecret(ctx context.Context, name string) (string, error) { | func (v *AzureKeyVault) GetSecret(ctx context.Context, name string) (string, error) { | ||||||
| 	secret, err := v.client.GetSecret(ctx, name, "", nil) | 	secret, err := v.client.GetSecret(ctx, name, "", nil) | ||||||
|  |  | ||||||
|  | @ -20,8 +20,7 @@ type Config struct { | ||||||
| 	TenantID        string                   `json:"tenant_id"` | 	TenantID        string                   `json:"tenant_id"` | ||||||
| 	ClientID        string                   `json:"client_id"` | 	ClientID        string                   `json:"client_id"` | ||||||
| 	URL             string                   `json:"url"` | 	URL             string                   `json:"url"` | ||||||
| 	CertPath     string                   `json:"cert_path"` | 	CertificatePath string                   `json:"certificate_path"` | ||||||
| 	CertPassword string                   `json:"cert_password"` // optional
 |  | ||||||
| 	Proxy           *proxyconfig.ProxyConfig `json:"proxy,omitempty"` | 	Proxy           *proxyconfig.ProxyConfig `json:"proxy,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -36,12 +35,12 @@ func (c *Config) Validate() error { | ||||||
| 		return fmt.Errorf("failed to parse url: %v", err) | 		return fmt.Errorf("failed to parse url: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if c.CertPath == "" { | 	if c.CertificatePath == "" { | ||||||
| 		return errors.New("cert path must be provided") | 		return errors.New("cert path must be provided") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if _, err := os.Stat(c.CertPath); err != nil { | 	if _, err := os.Stat(c.CertificatePath); err != nil { | ||||||
| 		return fmt.Errorf("cert path %q does not exist: %v", c.CertPath, err) | 		return fmt.Errorf("cert path %q does not exist: %v", c.CertificatePath, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err := c.Proxy.Validate(); err != nil { | 	if err := c.Proxy.Validate(); err != nil { | ||||||
|  | @ -57,12 +56,12 @@ func (c *Config) Client() (*azsecrets.Client, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Config) certClient() (*azsecrets.Client, error) { | func (c *Config) certClient() (*azsecrets.Client, error) { | ||||||
| 	data, err := os.ReadFile(c.CertPath) | 	data, err := os.ReadFile(c.CertificatePath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("failed to read cert file from path %q: %v", c.CertPath, err) | 		return nil, fmt.Errorf("failed to read cert file from path %q: %v", c.CertificatePath, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	certs, key, err := azidentity.ParseCertificates(data, []byte(c.CertPassword)) | 	certs, key, err := azidentity.ParseCertificates(data, nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("failed to parse certificates: %w", err) | 		return nil, fmt.Errorf("failed to parse certificates: %w", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -46,40 +46,35 @@ func TestConfigValidate_invalid(t *testing.T) { | ||||||
| 			TenantID:        "", | 			TenantID:        "", | ||||||
| 			ClientID:        clientID, | 			ClientID:        clientID, | ||||||
| 			URL:             url, | 			URL:             url, | ||||||
| 			CertPath:     certPath, | 			CertificatePath: certPath, | ||||||
| 			CertPassword: "", |  | ||||||
| 			Proxy:           proxy, | 			Proxy:           proxy, | ||||||
| 		}, | 		}, | ||||||
| 		"no client id": { | 		"no client id": { | ||||||
| 			TenantID:        tenantID, | 			TenantID:        tenantID, | ||||||
| 			ClientID:        "", | 			ClientID:        "", | ||||||
| 			URL:             url, | 			URL:             url, | ||||||
| 			CertPath:     certPath, | 			CertificatePath: certPath, | ||||||
| 			CertPassword: "", |  | ||||||
| 			Proxy:           proxy, | 			Proxy:           proxy, | ||||||
| 		}, | 		}, | ||||||
| 		"no url": { | 		"no url": { | ||||||
| 			TenantID:        tenantID, | 			TenantID:        tenantID, | ||||||
| 			ClientID:        clientID, | 			ClientID:        clientID, | ||||||
| 			URL:             "", | 			URL:             "", | ||||||
| 			CertPath:     certPath, | 			CertificatePath: certPath, | ||||||
| 			CertPassword: "", |  | ||||||
| 			Proxy:           proxy, | 			Proxy:           proxy, | ||||||
| 		}, | 		}, | ||||||
| 		"no jwt and no cert path": { | 		"no jwt and no cert path": { | ||||||
| 			TenantID:        tenantID, | 			TenantID:        tenantID, | ||||||
| 			ClientID:        clientID, | 			ClientID:        clientID, | ||||||
| 			URL:             url, | 			URL:             url, | ||||||
| 			CertPath:     "", | 			CertificatePath: "", | ||||||
| 			CertPassword: "", |  | ||||||
| 			Proxy:           proxy, | 			Proxy:           proxy, | ||||||
| 		}, | 		}, | ||||||
| 		"invalid proxy": { | 		"invalid proxy": { | ||||||
| 			TenantID:        tenantID, | 			TenantID:        tenantID, | ||||||
| 			ClientID:        clientID, | 			ClientID:        clientID, | ||||||
| 			URL:             url, | 			URL:             url, | ||||||
| 			CertPath:     certPath, | 			CertificatePath: certPath, | ||||||
| 			CertPassword: "", |  | ||||||
| 			Proxy: &proxyconfig.ProxyConfig{ | 			Proxy: &proxyconfig.ProxyConfig{ | ||||||
| 				HTTP: &proxyconfig.ProxyServerConfig{}, | 				HTTP: &proxyconfig.ProxyServerConfig{}, | ||||||
| 			}, | 			}, | ||||||
|  | @ -123,16 +118,14 @@ func TestValidate_valid(t *testing.T) { | ||||||
| 			TenantID:        tenantID, | 			TenantID:        tenantID, | ||||||
| 			ClientID:        clientID, | 			ClientID:        clientID, | ||||||
| 			URL:             url, | 			URL:             url, | ||||||
| 			CertPath:     certPath, | 			CertificatePath: certPath, | ||||||
| 			CertPassword: "", |  | ||||||
| 			Proxy:           proxy, | 			Proxy:           proxy, | ||||||
| 		}, | 		}, | ||||||
| 		"without proxy": { | 		"without proxy": { | ||||||
| 			TenantID:        tenantID, | 			TenantID:        tenantID, | ||||||
| 			ClientID:        clientID, | 			ClientID:        clientID, | ||||||
| 			URL:             url, | 			URL:             url, | ||||||
| 			CertPath:     certPath, | 			CertificatePath: certPath, | ||||||
| 			CertPassword: "", |  | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,8 +3,6 @@ package vault | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" |  | ||||||
| 	"strings" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/actions/actions-runner-controller/vault/azurekeyvault" | 	"github.com/actions/actions-runner-controller/vault/azurekeyvault" | ||||||
| ) | ) | ||||||
|  | @ -38,29 +36,3 @@ func (t VaultType) Validate() error { | ||||||
| 
 | 
 | ||||||
| // Compile-time checks
 | // Compile-time checks
 | ||||||
| var _ Vault = (*azurekeyvault.AzureKeyVault)(nil) | var _ Vault = (*azurekeyvault.AzureKeyVault)(nil) | ||||||
| 
 |  | ||||||
| // InitAll initializes all vaults based on the environment variables
 |  | ||||||
| // that start with the given prefix. It returns a map of vault types to their
 |  | ||||||
| // corresponding vault instances.
 |  | ||||||
| //
 |  | ||||||
| // Prefix is the namespace prefix used to filter environment variables.
 |  | ||||||
| // For example, the listener environment variable are prefixed with "LISTENER_", followed by the vault type, followed by the value.
 |  | ||||||
| //
 |  | ||||||
| // For example, listener has prefix "LISTENER_", has "AZURE_KEY_VAULT_" configured,
 |  | ||||||
| // and should read the vault URL. The environment variable will be "LISTENER_AZURE_KEY_VAULT_URL".
 |  | ||||||
| func InitAll(prefix string) (map[VaultType]Vault, error) { |  | ||||||
| 	envs := os.Environ() |  | ||||||
| 
 |  | ||||||
| 	result := make(map[VaultType]Vault) |  | ||||||
| 	for _, env := range envs { |  | ||||||
| 		if strings.HasPrefix(env, prefix+"AZURE_KEY_VAULT_") { |  | ||||||
| 			akv, err := azurekeyvault.FromEnv(prefix + "AZURE_KEY_VAULT_") |  | ||||||
| 			if err != nil { |  | ||||||
| 				return nil, fmt.Errorf("failed to instantiate azure key vault from env: %v", err) |  | ||||||
| 			} |  | ||||||
| 			result[VaultTypeAzureKeyVault] = akv |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return result, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue