Skip to content

Commit

Permalink
Store AWS creds in secret
Browse files Browse the repository at this point in the history
  • Loading branch information
Sudhindra Tirupati Nagaraj committed Aug 18, 2020
1 parent 4e9d582 commit 6629878
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 18 deletions.
23 changes: 18 additions & 5 deletions api/v1alpha2/awspcaissuer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,29 @@ type AWSPCAIssuerList struct {
Items []AWSPCAIssuer `json:"items"`
}

// SecretKeySelector contains the reference to a secret.
type SecretKeySelector struct {
// The key of the secret to select from. Must be a valid secret key.
// +optional
Key string `json:"key,omitempty"`
}

// AWSPCAProvisioner contains the configuration for requesting certificate from AWS
type AWSPCAProvisioner struct {
// Names is the name of the JWK provisioner.
AccessKey string `json:"accesskey"`
// The name of the secret in the pod's namespace to select from.
Name string `json:"name"`

// Reference to AWS access key
AccessKeyRef SecretKeySelector `json:"accesskeyRef"`

SecretKey string `json:"secretkey"`
// Reference to AWS secret key
SecretKeyRef SecretKeySelector `json:"secretkeyRef"`

Region string `json:"region"`
// Reference to AWS region
RegionRef SecretKeySelector `json:"regionRef"`

Arn string `json:"arn"`
// Reference to private CA ARN
ArnRef SecretKeySelector `json:"arnRef"`
}

// ConditionType represents a AWSPCAIssuer condition type.
Expand Down
19 changes: 19 additions & 0 deletions api/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

84 changes: 74 additions & 10 deletions controllers/awspcaissuer_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
api "github.com/awspca-issuer/api/v1alpha2"
"github.com/awspca-issuer/provisioners"
"github.com/go-logr/logr"
core "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"k8s.io/utils/clock"
Expand Down Expand Up @@ -60,8 +62,68 @@ func (r *AWSPCAIssuerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error
}

// Initialize and store the provisioner
p := provisioners.NewProvisioner(iss.Spec.Provisioner.AccessKey,
iss.Spec.Provisioner.SecretKey, iss.Spec.Provisioner.Arn, iss.Spec.Provisioner.Region)

// AWS access key, secret key, region, and private CA ARN are all stored as secrets
var secret core.Secret
var ok bool
var accessKey []byte
var secretKey []byte
var region []byte
var arn []byte

secretNamespaceName := types.NamespacedName{
Namespace: req.Namespace,
Name: iss.Spec.Provisioner.Name,
}

if err := r.Client.Get(ctx, secretNamespaceName, &secret); err != nil {
log.Error(err, "failed to retrieve AWS secrets", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
if apierrors.IsNotFound(err) {
statusReconciler.UpdateNoError(ctx, api.ConditionFalse, "NotFound", "Failed to retrieve AWS secrets: %v", err)
} else {
statusReconciler.UpdateNoError(ctx, api.ConditionFalse, "Error", "Failed to retrieve AWS secrets: %v", err)
}
return ctrl.Result{}, err
}

accessKey, ok = secret.Data[iss.Spec.Provisioner.AccessKeyRef.Key]

if !ok {
err := fmt.Errorf("secret %s does not contain key %s", secret.Name, iss.Spec.Provisioner.AccessKeyRef.Key)
log.Error(err, "failed to retrieve AWS access key from secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
statusReconciler.UpdateNoError(ctx, api.ConditionFalse, "NotFound", "Failed to retrieve AWS access key from secret: %v", err)
return ctrl.Result{}, err
}

secretKey, ok = secret.Data[iss.Spec.Provisioner.SecretKeyRef.Key]

if !ok {
err := fmt.Errorf("secret %s does not contain key %s", secret.Name, iss.Spec.Provisioner.SecretKeyRef.Key)
log.Error(err, "failed to retrieve AWS secret key from secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
statusReconciler.UpdateNoError(ctx, api.ConditionFalse, "NotFound", "Failed to retrieve AWS secret key from secret: %v", err)
return ctrl.Result{}, err
}

region, ok = secret.Data[iss.Spec.Provisioner.RegionRef.Key]

if !ok {
err := fmt.Errorf("secret %s does not contain key %s", secret.Name, iss.Spec.Provisioner.RegionRef.Key)
log.Error(err, "failed to retrieve AWS region from secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
statusReconciler.UpdateNoError(ctx, api.ConditionFalse, "NotFound", "Failed to retrieve AWS region from secret: %v", err)
return ctrl.Result{}, err
}

arn, ok = secret.Data[iss.Spec.Provisioner.ArnRef.Key]

if !ok {
err := fmt.Errorf("secret %s does not contain key %s", secret.Name, iss.Spec.Provisioner.ArnRef.Key)
log.Error(err, "failed to retrieve AWS Private CA ARN from secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
statusReconciler.UpdateNoError(ctx, api.ConditionFalse, "NotFound", "Failed to retrieve AWS Private CA ARN from secret: %v", err)
return ctrl.Result{}, err
}

p := provisioners.NewProvisioner(string(accessKey), string(secretKey),
string(region), string(arn))

issNamespaceName := types.NamespacedName{
Namespace: req.Namespace,
Expand All @@ -83,14 +145,16 @@ func (r *AWSPCAIssuerReconciler) SetupWithManager(mgr ctrl.Manager) error {

func validateAWSPCAIssuerSpec(s api.AWSPCAIssuerSpec) error {
switch {
case s.Provisioner.AccessKey == "":
return fmt.Errorf("spec.provisioner.accesskey cannot be empty")
case s.Provisioner.SecretKey == "":
return fmt.Errorf("spec.provisioner.secretkey cannot be empty")
case s.Provisioner.Region == "":
return fmt.Errorf("spec.provisioner.region cannot be empty")
case s.Provisioner.Arn == "":
return fmt.Errorf("spec.provisioner.arn cannot be empty")
case s.Provisioner.Name == "":
return fmt.Errorf("spec.provisioner.name cannot be empty")
case s.Provisioner.AccessKeyRef.Key == "":
return fmt.Errorf("spec.provisioner.accesskeyRef.key cannot be empty")
case s.Provisioner.SecretKeyRef.Key == "":
return fmt.Errorf("spec.provisioner.secretkeyRef.key cannot be empty")
case s.Provisioner.RegionRef.Key == "":
return fmt.Errorf("spec.provisioner.regionRef.key cannot be empty")
case s.Provisioner.ArnRef.Key == "":
return fmt.Errorf("spec.provisioner.arnRef.key cannot be empty")
default:
return nil
}
Expand Down
6 changes: 3 additions & 3 deletions provisioners/awspca.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ type AWSPCA struct {
type AWSPCAProvisioner struct {
accesskey string
secretkey string
arn string
region string
arn string
}

func NewProvisioner(accesskey string,
secretkey string, arn string, region string) (p *AWSPCAProvisioner) {
secretkey string, region string, arn string) (p *AWSPCAProvisioner) {

return &AWSPCAProvisioner{
accesskey: accesskey, secretkey: secretkey,arn: arn, region: region,
accesskey: accesskey, secretkey: secretkey, region: region, arn: arn,
}
}

Expand Down

0 comments on commit 6629878

Please sign in to comment.