Skip to content

Commit

Permalink
move to crds
Browse files Browse the repository at this point in the history
  • Loading branch information
argonaut0 committed Sep 29, 2023
1 parent 35823bc commit d71ad3a
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 100 deletions.
8 changes: 2 additions & 6 deletions operator-experiment/0-instanced-challenge-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@ spec:
spec:
type: object
properties:
resources:
type: array
items:
type: object
x-kubernetes-embedded-resource: true
x-kubernetes-preserve-unknown-fields: true
challengeTemplate:
type: string
scope: Namespaced
names:
plural: instancedchallenges
Expand Down
112 changes: 61 additions & 51 deletions operator-experiment/example-instchall.yaml
Original file line number Diff line number Diff line change
@@ -1,83 +1,93 @@
apiVersion: "k8s.maplebacon.org/unstable"
kind: InstancedChallenge
metadata:
name: nginx
name: blade-runner
namespace: challenges
spec:
resources:
- apiVersion: apps/v1
challengeTemplate: |
---
apiVersion: v1
kind: Service
metadata:
name: blade-runner-{{.ID}}
namespace: challenges
spec:
ports:
- name: web
port: 6969
targetPort: 6969
protocol: TCP
selector:
app: blade-runner-{{.ID}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
name: blade-runner-{{.ID}}
labels:
app: blade-runner-{{.ID}}
namespace: challenges
spec:
selector:
matchLabels:
app: nginx
replicas: 2
app: blade-runner-{{.ID}}
replicas: 1
template:
metadata:
labels:
app: nginx
app: blade-runner-{{.ID}}
spec:
enableServiceLinks: false
automountServiceAccountToken: false
containers:
- name: nginx
image: nginx:1.14.2
- name: blade-runner
image: us.gcr.io/maplectf/blade-runner:latest
imagePullPolicy: Always
ports:
- containerPort: 80
- apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: challenges
spec:
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 80
- apiVersion: networking.k8s.io/v1
- containerPort: 6969
name: web
securityContext:
allowPrivilegeEscalation: false
privileged: false
resources:
requests:
cpu: "75m"
memory: "70Mi"
limits:
cpu: "250m"
memory: "100Mi"
- name: redis
image: redis:latest
imagePullPolicy: Always
ports:
- containerPort: 6379
name: redis
securityContext:
allowPrivilegeEscalation: false
privileged: false
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
name: blade-runner-{{.ID}}
namespace: challenges
annotations:
cert-manager.io/issuer: "letsencrypt-prod"
certmanager.k8s.io/issuer: "letsencrypt-prod"
certmanager.k8s.io/acme-challenge-type: dns01
spec:
ingressClassName: nginx
ingressClassName: challenges-nginx
tls:
- hosts:
- nginx-test.ctf.maplebacon.org
secretName: nginx-test-tls
- "{{.ID}}.blade-runner.ctf.maplebacon.org"
secretName: blade-runner-tls
rules:
- host: nginx-test.ctf.maplebacon.org
- host: {{.ID}}.blade-runner.ctf.maplebacon.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
name: blade-runner-{{.ID}}
port:
number: 8080
- apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-prod
namespace: challenges
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: [email protected]
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
number: 6969
12 changes: 8 additions & 4 deletions src/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ type InstanceRecord struct {

func (r *InstanceRecord) MarshalJSON() ([]byte, error) {
type Alias InstanceRecord
return json.Marshal(&struct {
data := &struct {
*Alias
Expiry int64 `json:"stamp"`
Expiry string `json:"expiry"`
}{
Alias: (*Alias)(r),
Expiry: r.Expiry.Unix(),
})
Expiry: r.Expiry.Format(time.TimeOnly) + " UTC",
}
if r.Expiry.Before(time.Now()) {
data.Expiry = "Expired"
}
return json.Marshal(data)
}

func (in *Instancer) InitDB(file string) error {
Expand Down
51 changes: 26 additions & 25 deletions src/instancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func InitInstancer() (*Instancer, error) {
if err != nil {
log.Fatal().Err(err).Msg("could not load config")
}
log.Info().Int("count", len(in.config.Challenges)).Msg("read challenges from config")
//log.Info().Int("count", len(in.config.Challenges)).Msg("read challenges from config")
log.Debug().Str("value", in.config.ListenAddr).Msg("read listenAddr from config")

/* in.challengeObjs, err = UnmarshalChallenges(in.config.Challenges)
Expand All @@ -75,36 +75,22 @@ func InitInstancer() (*Instancer, error) {
}
log.Info().Int("count", len(in.challengeObjs)).Msg("parsed challenges") */
// Parse templates
in.challengeTmpls = make(map[string]*template.Template, len(in.config.Challenges))
for k, v := range in.config.Challenges {
tmpl, err := template.New("challenge").Parse(v)
if err != nil {
log.Error().Err(err).Str("challenge", k).Msg("could not parse a challenge template")
continue
}
in.challengeTmpls[k] = tmpl
}

/* in.challengeTmpls = make(map[string]*template.Template, len(in.config.Challenges))
for k, v := range in.config.Challenges {
tmpl, err := template.New("challenge").Parse(v)
if err != nil {
log.Error().Err(err).Str("challenge", k).Msg("could not parse a challenge template")
continue
}
in.challengeTmpls[k] = tmpl
} */
in.k8sConfig, err = rest.InClusterConfig()
if err != nil {
log.Fatal().Err(err).Msg("could not create kube-api client config")
}
rest.SetKubernetesDefaults(in.k8sConfig)
log.Debug().Str("config", fmt.Sprintf("%+v", in.k8sConfig)).Msg("loaded kube-api client config")

// Test CRDs
log.Debug().Msg("querying CRDs")
crdChallObjs, err := in.QueryInstancedChallenges("challenges")
if err != nil {
log.Debug().Err(err).Msg("error retrieving challenge definitions from CRDs")
} else {
for k, o := range crdChallObjs {
log.Debug().Str("challenge", k).Msg("parsed challenge from CRD")
for _, v := range o {
log.Debug().Str("kind", v.GetKind()).Str("name", v.GetName()).Str("challenge", k).Msg("parsed resource")
}
}
}
in.LoadCRDs()

err = in.InitDB("/data/instancer.db")
if err != nil {
Expand All @@ -115,6 +101,21 @@ func InitInstancer() (*Instancer, error) {
return &in, nil
}

func (in *Instancer) LoadCRDs() {
log := in.log
// Test CRDs
log.Debug().Msg("querying CRDs")
crdChallObjs, err := in.QueryInstancedChallenges("challenges")
if err != nil {
log.Debug().Err(err).Msg("error retrieving challenge definitions from CRDs")
}
for k := range crdChallObjs {
log.Info().Str("challenge", k).Msg("parsed challenge template")
}
log.Info().Int("count", len(crdChallObjs)).Msg("parsed challenges")
in.challengeTmpls = crdChallObjs
}

func (in *Instancer) DestoryExpiredInstances() {
log := in.log.With().Str("component", "instanced").Logger()
instances, err := in.ReadInstanceRecords()
Expand Down
23 changes: 10 additions & 13 deletions src/k8sclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strings"
"text/template"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -150,7 +151,7 @@ func (in *Instancer) GetObjectResource(unstructObj *unstructured.Unstructured) (
return mapping.Resource, nil
}

func (in *Instancer) QueryInstancedChallenges(namespace string) (map[string][]unstructured.Unstructured, error) {
func (in *Instancer) QueryInstancedChallenges(namespace string) (map[string]*template.Template, error) {
resource := schema.GroupVersionResource{
Group: "k8s.maplebacon.org",
Version: "unstable",
Expand All @@ -167,25 +168,21 @@ func (in *Instancer) QueryInstancedChallenges(namespace string) (map[string][]un
return nil, err
}

ret := make(map[string][]unstructured.Unstructured)
ret := make(map[string]*template.Template)

for _, c := range chalList.Items {
resources, found, err := unstructured.NestedSlice(c.Object, "spec", "resources")
tmplStr, found, err := unstructured.NestedString(c.Object, "spec", "challengeTemplate")
if err != nil || !found {
fmt.Printf("resources not found for challenge crd %v: error=%v", c.GetName(), err)
fmt.Printf("template not found for challenge crd %v: error=%v", c.GetName(), err)
continue
}

res := make([]unstructured.Unstructured, 0)

for _, r := range resources {
obj, ok := r.(map[string]interface{})
if !ok {
fmt.Printf("could not parse object")
}
res = append(res, unstructured.Unstructured{Object: obj})
tmpl, err := template.New("challenge").Parse(tmplStr)
if err != nil {
in.log.Error().Err(err).Str("challenge", c.GetName()).Msg("could not parse a challenge template")
continue
}
ret[c.GetName()] = res
ret[c.GetName()] = tmpl
}
return ret, nil
}
Expand Down
2 changes: 1 addition & 1 deletion src/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (in *Instancer) handleInstanceCreate(c echo.Context) error {
return c.JSON(http.StatusInternalServerError, "challenge deploy failed: contact admin")
}
c.Logger().Info("processed request to provision new instance")
return c.JSON(http.StatusAccepted, InstancesResponse{"created", chalName, rec.Id, fmt.Sprintf("http://%v.%v.ctf.maplebacon.org", rec.UUID, chalName)})
return c.JSON(http.StatusAccepted, InstancesResponse{"created", chalName, rec.Id, fmt.Sprintf("https://%v.%v.ctf.maplebacon.org", rec.UUID, chalName)})
}

func (in *Instancer) handleInstanceDelete(c echo.Context) error {
Expand Down

0 comments on commit d71ad3a

Please sign in to comment.