Skip to content

Commit

Permalink
feat(csv): install owned APIServices
Browse files Browse the repository at this point in the history
  • Loading branch information
njhale committed Oct 5, 2018
1 parent 363876e commit 0136a21
Showing 28 changed files with 2,215 additions and 43 deletions.
13 changes: 12 additions & 1 deletion Gopkg.lock

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

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -110,8 +110,8 @@ $(CODEGEN):
git clone --branch release-1.11 https://github.com/kubernetes/code-generator.git vendor/k8s.io/code-generator

pkg/package-server/generated/openapi/zz_generated.openapi.go:
go run vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go --logtostderr -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/k8s.io/apimachinery/pkg/version,./pkg/package-server/apis/packagemanifest/v1alpha1 -p github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/generated/openapi/ -O zz_generated.openapi -h boilerplate.go.txt -r /dev/null

go run vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go --logtostderr -i ./vendor/k8s.io/apimachinery/pkg/runtime,./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/k8s.io/apimachinery/pkg/version,./pkg/package-server/apis/packagemanifest/v1alpha1 -p github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/generated/openapi/ -O zz_generated.openapi -h boilerplate.go.txt -r /dev/null
clean-openapi:
rm -rf pkg/package-server/generated/openapi

25 changes: 19 additions & 6 deletions deploy/chart/templates/30_02-clusterserviceversion.crd.yaml
Original file line number Diff line number Diff line change
@@ -189,21 +189,28 @@ spec:
items:
type: object
required:
- name
- group
- version
- kind
- deploymentName
- displayName
- description
properties:
name:
group:
type: string
description: Fully qualified name of the APIService (e.g. my-resource-v1.app.coreos.com)
description: Group of the APIService (e.g. app.coreos.com)
version:
type: string
description: The version field of the APIService
kind:
type: string
description: The kind field of the APIService
deploymentName:
type: string
description: Name of the extension api-server's deployment
containerPort:
type: number
description: Port where the extension api-server serves TLS traffic
displayName:
type: string
description: A human-readable name for the APIService.
@@ -315,21 +322,27 @@ spec:
items:
type: object
required:
- name
- group
- version
- kind
- displayName
- description
properties:
name:
group:
type: string
description: Fully qualified name of the APIService (e.g. my-resource-v1.app.coreos.com)
description: Group of the APIService (e.g. app.coreos.com)
version:
type: string
description: The version field of the APIService
kind:
type: string
description: The kind field of the APIService
deploymentName:
type: string
description: Name of the extension api-server's deployment
containerPort:
type: number
description: Port where the extension api-server serves TLS traffic
displayName:
type: string
description: A human-readable name for the APIService.
69 changes: 66 additions & 3 deletions pkg/api/apis/operators/v1alpha1/clusterserviceversion_types.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ package v1alpha1

import (
"encoding/json"
"fmt"
"sort"

"github.com/coreos/go-semver/semver"
@@ -65,9 +66,11 @@ type CRDDescription struct {

// APIServiceDescription provides details to OLM about apis provided via aggregation
type APIServiceDescription struct {
Name string `json:"name"`
Group string `json:"group"`
Version string `json:"version"`
Kind string `json:"kind"`
DeploymentName string `json:"deploymentName,omitempty"`
ContainerPort int32 `json:"containerPort,omitempty"`
DisplayName string `json:"displayName,omitempty"`
Description string `json:"description,omitempty"`
Resources []APIResourceReference `json:"resources,omitempty"`
@@ -334,11 +337,71 @@ func (csv ClusterServiceVersion) GetAllCRDDescriptions() []CRDDescription {
func (csv ClusterServiceVersion) GetAllAPIServiceDescriptions() []APIServiceDescription {
set := make(map[string]APIServiceDescription)
for _, required := range csv.Spec.APIServiceDefinitions.Required {
set[required.Name] = required
name := fmt.Sprintf("%s.%s", required.Version, required.Group)
set[name] = required
}

for _, owned := range csv.Spec.APIServiceDefinitions.Owned {
set[owned.Name] = owned
name := fmt.Sprintf("%s.%s", owned.Version, owned.Group)
set[name] = owned
}

keys := make([]string, 0)
for key := range set {
keys = append(keys, key)
}
sort.StringSlice(keys).Sort()

descs := make([]APIServiceDescription, 0)
for _, key := range keys {
descs = append(descs, set[key])
}

return descs
}

// GetRequiredAPIServiceDescriptions returns a deduplicated set of required APIServiceDescriptions
// with the intersection of required and owned removed
// Equivalent to the set subtraction required - owned
//
// Descriptions are returned in alphabetical order.
func (csv ClusterServiceVersion) GetRequiredAPIServiceDescriptions() []APIServiceDescription {
set := make(map[string]APIServiceDescription)
for _, required := range csv.Spec.APIServiceDefinitions.Required {
name := fmt.Sprintf("%s.%s", required.Version, required.Group)
set[name] = required
}

// Remove any shared owned from the set
for _, owned := range csv.Spec.APIServiceDefinitions.Owned {
name := fmt.Sprintf("%s.%s", owned.Version, owned.Group)
if _, ok := set[name]; ok {
delete(set, name)
}
}

keys := make([]string, 0)
for key := range set {
keys = append(keys, key)
}
sort.StringSlice(keys).Sort()

descs := make([]APIServiceDescription, 0)
for _, key := range keys {
descs = append(descs, set[key])
}

return descs
}

// GetOwnedAPIServiceDescriptions returns a deduplicated set of owned APIServiceDescriptions
//
// Descriptions are returned in alphabetical order.
func (csv ClusterServiceVersion) GetOwnedAPIServiceDescriptions() []APIServiceDescription {
set := make(map[string]APIServiceDescription)
for _, owned := range csv.Spec.APIServiceDefinitions.Owned {
name := fmt.Sprintf("%s.%s", owned.Version, owned.Group)
set[name] = owned
}

keys := make([]string, 0)
121 changes: 121 additions & 0 deletions pkg/controller/certs/certs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package certs

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"time"
)

// KeyPair stores an x509 certificate and its ECDSA private key
type KeyPair struct {
Cert *x509.Certificate
Priv *ecdsa.PrivateKey
}

// ToPEM returns the PEM encoded cert pair
func (kp *KeyPair) ToPEM() (certPEM []byte, privPEM []byte, err error) {
// PEM encode private key
privDER, err := x509.MarshalECPrivateKey(kp.Priv)
if err != nil {
return
}
privBlock := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: privDER,
}
privPEM = pem.EncodeToMemory(privBlock)

// PEM encode cert
certBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: kp.Cert.Raw,
}
certPEM = pem.EncodeToMemory(certBlock)

return
}

func GenerateCA() (*KeyPair, error) {
caDetails := &x509.Certificate{
//TODO(Nick): figure out what to use for a SerialNumber
SerialNumber: big.NewInt(1653),
Subject: pkix.Name{
Organization: []string{"Red Hat, Inc."},
},
NotBefore: time.Now(),
// Valid for 2 years
NotAfter: time.Now().AddDate(2, 0, 0),
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}

privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}

publicKey := &privateKey.PublicKey
certRaw, err := x509.CreateCertificate(rand.Reader, caDetails, caDetails, publicKey, privateKey)
if err != nil {
return nil, err
}

cert, err := x509.ParseCertificate(certRaw)
if err != nil {
return nil, err
}

ca := &KeyPair{
Cert: cert,
Priv: privateKey,
}

return ca, nil
}

func CreateSignedServingPair(ca *KeyPair, hosts []string) (*KeyPair, error) {
certDetails := &x509.Certificate{
//TODO(Nick): figure out what to use for a SerialNumber
SerialNumber: big.NewInt(1653),
Subject: pkix.Name{
Organization: []string{"Red Hat, Inc."},
},
NotBefore: time.Now(),
// Valid for 2 years
NotAfter: time.Now().AddDate(2, 0, 0),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
DNSNames: hosts,
}

privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}

publicKey := &privateKey.PublicKey
certRaw, err := x509.CreateCertificate(rand.Reader, certDetails, ca.Cert, publicKey, ca.Priv)
if err != nil {
return nil, err
}

cert, err := x509.ParseCertificate(certRaw)
if err != nil {
return nil, err
}

servingCert := &KeyPair{
Cert: cert,
Priv: privateKey,
}

return servingCert, nil
}
Loading

0 comments on commit 0136a21

Please sign in to comment.