Skip to content

Commit

Permalink
Merge pull request #6 from sysmatrix1/add-venafi-support
Browse files Browse the repository at this point in the history
add venafi support
  • Loading branch information
etsauer authored Oct 3, 2018
2 parents eb870f6 + 2fb1947 commit 854d841
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 0 deletions.
113 changes: 113 additions & 0 deletions deploy/cert-operator-template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
apiVersion: v1
kind: Template
version: v1alpha1
metadata:
name: cert-operator-template
objects:
- kind: CustomResourceDefinition
apiVersion: apiextensions.k8s.io/v1beta1
metadata:
name: cert-operators.openshift.io
spec:
group: openshift.io
version: v1alpha1
names:
kind: Cert-Operator
listKind: Cert-OperatorList
plural: cert-operators
singular: ${NAME}
scope: Namespaced
- kind: Cert-Operator
apiVersion: openshift.io/v1alpha1
metadata:
name: ${NAME}
- kind: Deployment
apiVersion: apps/v1beta1
metadata:
name: ${NAME}
labels:
app: ${NAME}
spec:
replicas: 1
selector:
matchLabels:
app: ${NAME}
template:
metadata:
labels:
app: ${NAME}
spec:
serviceAccountName: ${SERVICE_ACCOUNT_NAME}
containers:
- name: ${NAME}
image: docker-registry.default.svc:5000/${NAMESPACE}/${NAME}:${TAG}
ports:
- containerPort: 60000
name: metrics
command:
- cert-operator
imagePullPolicy: Always
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: OPERATOR_NAME
value: ${NAME}
- name: NOTIFIER_TYPE
value: ${NOTIFIER_TYPE}
- name: WEBHOOK_URL
value: ${WEBHOOK_URL}
- name: VENAFI_API_URL
value: ${VENAFI_API_URL}
- name: VENAFI_USER_NAME
value: ${VENAFI_USER_NAME}
- name: VENAFI_PASSWORD
value: ${VENAFI_PASSWORD}
- name: VENAFI_CERT_ZONE
value: ${VENAFI_CERT_ZONE}
parameters:
- description: "The name assigned to all of the frontend objects defined in this template."
displayName: "Name"
name: NAME
required: true
value: "cert-operator"
- description: "Namespace in which the ImageStreams for operator images are
installed. You should only need to modify this if you've installed the ImageStreams in a
different namespace/project."
name: NAMESPACE
required: true
value: "infrastructure-jobs"
- description: "The tag for the iamge"
name: TAG
displayName: "Image Tag"
required: true
value: "latest"
- description: "The Venafi API URL"
name: VENAFI_API_URL
value: "https://venafi-tppurl/vedsdk"
required: true
- description: "The Venafi user name"
name: VENAFI_USER_NAME
value: "venafiusername"
required: true
- description: "The Venafi password"
name: VENAFI_PASSWORD
value: "venafipassword"
required: true
- description: "The Venafi cert zone"
name: VENAFI_CERT_ZONE
value: "ABC Company\\Dev"
required: true
- description: "The Slack webhook"
name: WEBHOOK_URL
value: "http://hooks.slack.com/services/..."
required: false
- description: "Notifier type"
name: NOTIFIER_TYPE
value: "slack"
required: false
- description: "Service account name"
name: SERVICE_ACCOUNT_NAME
value: "serviceaccountname"
required: true
104 changes: 104 additions & 0 deletions pkg/certs/venafi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package certs

import (
"fmt"
"os"
"time"

"github.com/Venafi/govcert"
vcert "github.com/Venafi/govcert/embedded"
"github.com/hashicorp/terraform/helper/resource"
"github.com/sirupsen/logrus"
)

type VenafiProvider struct {
}

func (p *VenafiProvider) Provision(host string, validFrom string, validFor time.Duration, isCA bool, rsaBits int, ecdsaCurve string) (keypair KeyPair, certError error) {

if len(host) == 0 {
return KeyPair{}, NewErrBadHost("host cannot be empty")
}
logrus.Infof("Creating Venafi certificate for :" + host)
logrus.Infof("Venafi Zone: " + os.Getenv("VENAFI_CERT_ZONE"))

var notBefore time.Time
var err error
if len(validFrom) == 0 {
notBefore = time.Now()
} else {
notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
if err != nil {
return KeyPair{}, NewCertError("Failed to parse creation date: " + err.Error())
}
}

notAfter := notBefore.Add(validFor)

username := os.Getenv("VENAFI_USER_NAME")
password := os.Getenv("VENAFI_PASSWORD")
url := os.Getenv("VENAFI_API_URL")
venafi := vcert.NewClientTPP(username, password, url)
enrollreq := &govcert.EnrollReq{
CommonName: host,
Zone: os.Getenv("VENAFI_CERT_ZONE")}

resp, err := venafi.Do(enrollreq)
if err != nil {
return KeyPair{}, NewCertError("Failed to create certificate: " + err.Error())
}
respmap, err := resp.JSONBody()
if err != nil {
return KeyPair{}, NewCertError("Failed to create certificate: " + err.Error())
}
var cert, key []byte

key = []byte(respmap["PrivateKey"].(string))

if !resp.Pending() {
cert = []byte(respmap["Certificate"].(string))

if err != nil {
return KeyPair{}, NewCertError("Failed to create certificate: " + err.Error())
}
return KeyPair{
cert,
key,
notAfter}, nil
}
id, err := resp.RequestID()
if err != nil {
return KeyPair{}, NewCertError("Failed to create certificate: " + err.Error())
}
pickupreq := &govcert.PickupReq{
PickupID: id,
}
retryerr := resource.Retry(time.Duration(300)*time.Second, func() *resource.RetryError {
resp, err = venafi.Do(pickupreq)
if err != nil {
return resource.NonRetryableError(err)
}
if resp.Pending() {
return resource.RetryableError(fmt.Errorf("Certificate Issue pending"))
}

return nil
})
if retryerr != nil {
return KeyPair{}, NewCertError("Failed to create certificate: " + retryerr.Error())
}

respmap, err = resp.JSONBody()
if err != nil {
return KeyPair{}, NewCertError("Failed to create certificate: " + err.Error())
}
cert = []byte(respmap["Certificate"].(string))

return KeyPair{
cert,
key,
notAfter}, nil
}
func (p *VenafiProvider) Deprovision(host string) error {
return nil
}
3 changes: 3 additions & 0 deletions pkg/stub/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ func NewHandler(config Config) sdk.Handler {
provider = new(certs.NoneProvider)
case "self-signed":
provider = new(certs.SelfSignedProvider)
case "venafi":
logrus.Infof("Venafi Cert provider.")
provider = new(certs.VenafiProvider)
default:
panic("There was a problem detecting which provider to configure. " +
"Provider kind `" + config.Provider.Kind + "` is invalid.")
Expand Down
8 changes: 8 additions & 0 deletions tmp/build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
FROM alpine:3.6

RUN apk update && \
apk add libc6-compat && \
apk add ca-certificates
#Uncomment below lines to copy venafi's public certificate to the docker container.
#ADD venafi-tpp-cert.pem /usr/local/share/ca-certificates/venafi-tpp-cert.pem
#RUN update-ca-certificates

RUN adduser -D cert-operator

USER cert-operator

ADD tmp/_output/bin/cert-operator /usr/local/bin/cert-operator

0 comments on commit 854d841

Please sign in to comment.