gerrit: auto configure ssh keys
Change-Id: I9c3091e4bb998fa6c846c3c60c2801c7daa45bcf
diff --git a/core/installer/app.go b/core/installer/app.go
index 3656231..64c4078 100644
--- a/core/installer/app.go
+++ b/core/installer/app.go
@@ -285,6 +285,11 @@
}
}
}
+
+#SSHKey: {
+ public: string
+ private: string
+}
`
type appConfig struct {
diff --git a/core/installer/app_test.go b/core/installer/app_test.go
index 237c806..0dcccda 100644
--- a/core/installer/app_test.go
+++ b/core/installer/app_test.go
@@ -159,6 +159,10 @@
"ingressClass": "id-ingress-private",
"domain": "p.bar.ge",
},
+ "key": map[string]any{
+ "public": "foo",
+ "private": "bar",
+ },
},
}
rendered, err := a.Render(d)
diff --git a/core/installer/keys.go b/core/installer/keys.go
index d3dd1d7..3e3d84c 100644
--- a/core/installer/keys.go
+++ b/core/installer/keys.go
@@ -7,3 +7,7 @@
func NewSSHKeyPair(path string) (*keygen.KeyPair, error) {
return keygen.New(path, keygen.WithKeyType(keygen.Ed25519))
}
+
+func NewECDSASSHKeyPair(path string) (*keygen.KeyPair, error) {
+ return keygen.New(path, keygen.WithKeyType(keygen.ECDSA))
+}
diff --git a/core/installer/repoio.go b/core/installer/repoio.go
index 01a8f91..ffbdcb0 100644
--- a/core/installer/repoio.go
+++ b/core/installer/repoio.go
@@ -395,10 +395,22 @@
func deriveValues(values any, schema Schema, networks []Network) (map[string]any, error) {
ret := make(map[string]any)
- for k, v := range values.(map[string]any) { // TODO(giolekva): validate
- def, ok := schema.Fields()[k]
+ for k, def := range schema.Fields() {
+ // TODO(gio): validate that it is map
+ v, ok := values.(map[string]any)[k]
+ // TODO(gio): if missing use default value
if !ok {
- return nil, fmt.Errorf("Field not found: %s", k)
+ if def.Kind() == KindSSHKey {
+ key, err := NewECDSASSHKeyPair("tmp")
+ if err != nil {
+ return nil, err
+ }
+ ret[k] = map[string]string{
+ "public": string(key.RawAuthorizedKey()),
+ "private": string(key.RawPrivateKey()),
+ }
+ }
+ continue
}
switch def.Kind() {
case KindBoolean:
@@ -417,6 +429,12 @@
return nil, err
}
ret[k] = r
+ case KindSSHKey:
+ r, err := deriveValues(v, SSHKeySchema, networks)
+ if err != nil {
+ return nil, err
+ }
+ ret[k] = r
case KindStruct:
r, err := deriveValues(v, def, networks)
if err != nil {
diff --git a/core/installer/schema.go b/core/installer/schema.go
index a692ecf..b96cc13 100644
--- a/core/installer/schema.go
+++ b/core/installer/schema.go
@@ -17,6 +17,7 @@
KindStruct = 2
KindNetwork = 3
KindAuth = 5
+ KindSSHKey = 6
KindNumber = 4
)
@@ -32,6 +33,13 @@
},
}
+var SSHKeySchema Schema = structSchema{
+ fields: map[string]Schema{
+ "public": basicSchema{KindString},
+ "private": basicSchema{KindString},
+ },
+}
+
const networkSchema = `
#Network: {
name: string
@@ -82,6 +90,30 @@
return false
}
+const sshKeySchema = `
+#SSHKey: {
+ public: string
+ private: string
+}
+
+value: { %s }
+`
+
+func isSSHKey(v cue.Value) bool {
+ if v.Value().Kind() != cue.StructKind {
+ return false
+ }
+ s := fmt.Sprintf(sshKeySchema, fmt.Sprintf("%#v", v))
+ c := cuecontext.New()
+ u := c.CompileString(s)
+ sshKey := u.LookupPath(cue.ParsePath("#SSHKey"))
+ vv := u.LookupPath(cue.ParsePath("value"))
+ if err := sshKey.Subsume(vv); err == nil {
+ return true
+ }
+ return false
+}
+
type basicSchema struct {
kind Kind
}
@@ -119,6 +151,8 @@
return basicSchema{KindNetwork}, nil
} else if isAuth(v) {
return basicSchema{KindAuth}, nil
+ } else if isSSHKey(v) {
+ return basicSchema{KindSSHKey}, nil
}
s := structSchema{make(map[string]Schema)}
f, err := v.Fields(cue.Schema())
diff --git a/core/installer/values-tmpl/gerrit.cue b/core/installer/values-tmpl/gerrit.cue
index 5045e52..be8336b 100644
--- a/core/installer/values-tmpl/gerrit.cue
+++ b/core/installer/values-tmpl/gerrit.cue
@@ -1,6 +1,7 @@
input: {
network: #Network
subdomain: string
+ key: #SSHKey
}
_domain: "\(input.subdomain).\(input.network.domain)"
@@ -175,26 +176,16 @@
etc: {
secret: {
// TODO(gio): auto generate
- ssh_host_ecdsa_key: ###"""
- -----BEGIN OPENSSH PRIVATE KEY-----
- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
- 1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTLpTYrZ3zFkfRda+q0O3nr119UeN1M
- H4Ds59cN8NxLpSLZpWn7vLxigN2VCP373Lq5ulUbDojW5qvF2gGppA+4AAAAsHSkAHN0pA
- BzAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMulNitnfMWR9F1r
- 6rQ7eevXX1R43UwfgOzn1w3w3EulItmlafu8vGKA3ZUI/fvcurm6VRsOiNbmq8XaAamkD7
- gAAAAhAOzrB8wjiWKzKsrzepkgFbs/CoIT8TBdaPv2aLWPcZr4AAAAFmdlcnJpdEBwLnYw
- LmRvZG8uY2xvdWQB
- -----END OPENSSH PRIVATE KEY-----
- """###
- "ssh_host_ecdsa_key.pub": "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMulNitnfMWR9F1r6rQ7eevXX1R43UwfgOzn1w3w3EulItmlafu8vGKA3ZUI/fvcurm6VRsOiNbmq8XaAamkD7g="
+ ssh_host_ecdsa_key: input.key.private
+ "ssh_host_ecdsa_key.pub": input.key.public
}
config: {
- "replication.config": ###"""
+ "replication.config": """
[gerrit]
autoReload = false
replicateOnStartup = true
- defaultForceUpdate = true"""###
- "gerrit.config": ###"""
+ defaultForceUpdate = true"""
+ "gerrit.config": """
[gerrit]
basePath = git # FIXED
serverId = gerrit-1
@@ -203,17 +194,15 @@
# LoadBalancer's external IP. This can only be done manually after installing
# the chart, when you know the external IP the LoadBalancer got from the
# cluster.
- canonicalWebUrl = https://gerrit.p.v0.dodo.cloud
+ canonicalWebUrl = https://\(_domain)
disableReverseDnsLookup = true
[index]
type = LUCENE
[auth]
type = HTTP
httpHeader = X-User
- emailFormat = '{0}@v0.dodo.cloud'
- # loginUrl = https://accounts-ui.v0.dodo.cloud/
- # loginText = Sign In with dodo
- logoutUrl = https://accounts-ui.v0.dodo.cloud/logout
+ emailFormat = '{0}@\(global.domain)'
+ logoutUrl = https://accounts-ui.\(global.domain)/logout
gitBasicAuthPolicy = HTTP
userNameToLowerCase = true
userNameCaseInsensitive = true
@@ -228,7 +217,7 @@
timeout = 120 s
[user]
name = Gerrit Code Review
- email = gerrit@p.v0.dodo.cloud
+ email = gerrit@\(global.domain)
anonymousCoward = Unnamed User
[cache]
directory = cache
@@ -239,7 +228,7 @@
javaOptions = -Xms200m
# Has to be lower than 'gerrit.resources.limits.memory'. Also
# consider memories used by other applications in the container.
- javaOptions = -Xmx4g"""###
+ javaOptions = -Xmx4g"""
}
}
}
diff --git a/core/installer/welcome/appmanager-tmpl/app.html b/core/installer/welcome/appmanager-tmpl/app.html
index 088a4c5..09e1f9b 100644
--- a/core/installer/welcome/appmanager-tmpl/app.html
+++ b/core/installer/welcome/appmanager-tmpl/app.html
@@ -42,6 +42,20 @@
<span>Authentication Groups</span>
</label>
<input type="text" name="authGroups" oninput="valueChanged('{{- $name -}}.groups', this.value)" {{ if $readonly }}disabled{{ end }} value="{{ $authGroups }}" />
+ {{ else if eq $schema.Kind 6 }}
+ {{ $sshKey := index $data $name }}
+ {{ $public := "" }}
+ {{ $private := "" }}
+ {{ if $sshKey }}{{ $public = index $sshKey "public" }}{{ end }}
+ {{ if $sshKey }}{{ $private = index $sshKey "private" }}{{ end }}
+ <label for="{{ $name }}-public">
+ <span>Public Key</span>
+ </label>
+ <textarea name="{{ $name }}-public" disabled>{{ $public }}</textarea>
+ <label for="{{ $name }}-private">
+ <span>Private Key</span>
+ </label>
+ <textarea name="{{ $name }}-private" disabled>{{ $private }}</textarea>
{{ end }}
{{ end }}
{{ end }}