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 err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create Azure Key Vault client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if config.VaultLookupKey == "" {
|
vault = akv
|
||||||
panic(fmt.Errorf("vault type set to %q, but lookup key is empty", config.VaultType))
|
default:
|
||||||
}
|
return nil, fmt.Errorf("unsupported vault type: %s", config.VaultType)
|
||||||
|
|
||||||
vaults, err := vault.InitAll("LISTENER_")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to initialize vaults: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
vault, ok := vaults[config.VaultType]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("vault %q is not initialized", 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"
|
||||||
|
|
@ -19,28 +20,20 @@ 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")
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@ import (
|
||||||
|
|
||||||
// AzureKeyVault is a struct that holds the Azure Key Vault client.
|
// AzureKeyVault is a struct that holds the Azure Key Vault client.
|
||||||
type Config struct {
|
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"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() error {
|
func (c *Config) Validate() error {
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,43 +43,38 @@ func TestConfigValidate_invalid(t *testing.T) {
|
||||||
tt := map[string]*Config{
|
tt := map[string]*Config{
|
||||||
"empty": {},
|
"empty": {},
|
||||||
"no tenant id": {
|
"no tenant id": {
|
||||||
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{},
|
||||||
},
|
},
|
||||||
|
|
@ -120,19 +115,17 @@ func TestValidate_valid(t *testing.T) {
|
||||||
|
|
||||||
tt := map[string]*Config{
|
tt := map[string]*Config{
|
||||||
"with cert": {
|
"with cert": {
|
||||||
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