Add secrets support (#14)

This commit is contained in:
2023-02-14 20:18:41 -07:00
parent 6d2936393b
commit bfd05b6a8a
5 changed files with 395 additions and 69 deletions
+178 -29
View File
@@ -14,15 +14,52 @@ import (
var log = logging.MustGetLogger("cursorius-server") var log = logging.MustGetLogger("cursorius-server")
func createSchema(db database.Database) (graphql.Schema, error) { func createSchema(db database.Database) (graphql.Schema, error) {
credentialType := graphql.NewObject(graphql.ObjectConfig{ secretType := graphql.NewObject(graphql.ObjectConfig{
Name: "Credential", Name: "Secret",
Description: "A secret available for use inside of a pipeline.",
Fields: graphql.Fields{
"id": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The id of the secret.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if secret, ok := p.Source.(database.Secret); ok {
return secret.Id, nil
}
return nil, nil
},
},
"name": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The name of the secret.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if secret, ok := p.Source.(database.Secret); ok {
return secret.Name, nil
}
return nil, nil
},
},
"secret": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The secret.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if secret, ok := p.Source.(database.Secret); ok {
return secret.Secret, nil
}
return nil, nil
},
},
},
})
cloneCredentialType := graphql.NewObject(graphql.ObjectConfig{
Name: "CloneCredential",
Description: "A credential for authenticating with the pipeline source host.", Description: "A credential for authenticating with the pipeline source host.",
Fields: graphql.Fields{ Fields: graphql.Fields{
"id": &graphql.Field{ "id": &graphql.Field{
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
Description: "The id of the credential.", Description: "The id of the credential.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if credential, ok := p.Source.(database.Credential); ok { if credential, ok := p.Source.(database.CloneCredential); ok {
return credential.Id, nil return credential.Id, nil
} }
return nil, nil return nil, nil
@@ -32,7 +69,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
Description: "The name of the credential.", Description: "The name of the credential.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if credential, ok := p.Source.(database.Credential); ok { if credential, ok := p.Source.(database.CloneCredential); ok {
return credential.Name, nil return credential.Name, nil
} }
return nil, nil return nil, nil
@@ -42,7 +79,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
Description: "The credential type.", Description: "The credential type.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if credential, ok := p.Source.(database.Credential); ok { if credential, ok := p.Source.(database.CloneCredential); ok {
return credential.Type, nil return credential.Type, nil
} }
return nil, nil return nil, nil
@@ -52,7 +89,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
Description: "The username to user with the credential.", Description: "The username to user with the credential.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if credential, ok := p.Source.(database.Credential); ok { if credential, ok := p.Source.(database.CloneCredential); ok {
return credential.Username, nil return credential.Username, nil
} }
return nil, nil return nil, nil
@@ -62,7 +99,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
Description: "The secret for the credential.", Description: "The secret for the credential.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if credential, ok := p.Source.(database.Credential); ok { if credential, ok := p.Source.(database.CloneCredential); ok {
return credential.Secret, nil return credential.Secret, nil
} }
return nil, nil return nil, nil
@@ -210,16 +247,28 @@ func createSchema(db database.Database) (graphql.Schema, error) {
return nil, nil return nil, nil
}, },
}, },
"credentialId": &graphql.Field{ "cloneCredential": &graphql.Field{
Type: graphql.String, Type: cloneCredentialType,
Description: "The configured credential for cloning the pipeline source.", Description: "The configured credential for cloning the pipeline source.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if pipeline, ok := p.Source.(database.Pipeline); ok { if pipeline, ok := p.Source.(database.Pipeline); ok {
return pipeline.Credential, nil if pipeline.CloneCredential != nil {
return db.GetCloneCredentialById(*pipeline.CloneCredential)
}
} }
return nil, nil return nil, nil
}, },
}, },
"secrets": &graphql.Field{
Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(secretType))),
Description: "The list of secrets for the pipeline.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if pipeline, ok := p.Source.(database.Pipeline); ok {
return db.GetSecretsForPipeline(pipeline.Id)
}
return []database.Secret{}, nil
},
},
"webhooks": &graphql.Field{ "webhooks": &graphql.Field{
Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(webhookType))), Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(webhookType))),
Description: "The list of webhooks for the pipeline.", Description: "The list of webhooks for the pipeline.",
@@ -269,8 +318,8 @@ func createSchema(db database.Database) (graphql.Schema, error) {
return db.GetPipelines() return db.GetPipelines()
}, },
}, },
"Credential": &graphql.Field{ "CloneCredential": &graphql.Field{
Type: credentialType, Type: cloneCredentialType,
Args: graphql.FieldConfigArgument{ Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{ "id": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
@@ -282,16 +331,23 @@ func createSchema(db database.Database) (graphql.Schema, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return db.GetCredentialById(id) return db.GetCloneCredentialById(id)
}, },
}, },
"Credentials": &graphql.Field{ "CloneCredentials": &graphql.Field{
Type: graphql.NewNonNull(graphql.NewList(credentialType)), Type: graphql.NewNonNull(graphql.NewList(cloneCredentialType)),
Args: graphql.FieldConfigArgument{}, Args: graphql.FieldConfigArgument{},
Resolve: func(p graphql.ResolveParams) (interface{}, error) { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return db.GetCredentials() return db.GetCredentials()
}, },
}, },
"Secrets": &graphql.Field{
Type: graphql.NewNonNull(graphql.NewList(secretType)),
Args: graphql.FieldConfigArgument{},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return db.GetSecrets()
},
},
}, },
}) })
@@ -311,7 +367,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
"pollInterval": &graphql.ArgumentConfig{ "pollInterval": &graphql.ArgumentConfig{
Type: graphql.Int, Type: graphql.Int,
}, },
"credentialId": &graphql.ArgumentConfig{ "cloneCredentialId": &graphql.ArgumentConfig{
Type: graphql.String, Type: graphql.String,
}, },
}, },
@@ -324,7 +380,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
} }
var credential *uuid.UUID var credential *uuid.UUID
if credentialVal, ok := params.Args["credentialId"]; ok { if credentialVal, ok := params.Args["cloneCredentialId"]; ok {
id, err := uuid.Parse(credentialVal.(string)) id, err := uuid.Parse(credentialVal.(string))
if err != nil { if err != nil {
return nil, err return nil, err
@@ -375,9 +431,9 @@ func createSchema(db database.Database) (graphql.Schema, error) {
return webhook, nil return webhook, nil
}, },
}, },
"createCredential": &graphql.Field{ "createCloneCredential": &graphql.Field{
Type: credentialType, Type: cloneCredentialType,
Description: "Create a new credential", Description: "Create a new CloneCredential",
Args: graphql.FieldConfigArgument{ Args: graphql.FieldConfigArgument{
"name": &graphql.ArgumentConfig{ "name": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String), Type: graphql.NewNonNull(graphql.String),
@@ -396,7 +452,7 @@ func createSchema(db database.Database) (graphql.Schema, error) {
credential, err := db.CreateCredential( credential, err := db.CreateCredential(
params.Args["name"].(string), params.Args["name"].(string),
database.CredentialType(params.Args["type"].(string)), database.CloneCredentialType(params.Args["type"].(string)),
params.Args["username"].(string), params.Args["username"].(string),
params.Args["secret"].(string), params.Args["secret"].(string),
) )
@@ -406,11 +462,34 @@ func createSchema(db database.Database) (graphql.Schema, error) {
return credential, nil return credential, nil
}, },
}, },
"setPipelineCredential": &graphql.Field{ "createSecret": &graphql.Field{
Type: pipelineType, Type: secretType,
Description: "Add an credential to a pipeline", Description: "Create a new secret",
Args: graphql.FieldConfigArgument{ Args: graphql.FieldConfigArgument{
"credentialId": &graphql.ArgumentConfig{ "name": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
"secret": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
secret, err := db.CreateSecret(
params.Args["name"].(string),
params.Args["secret"].(string),
)
if err != nil {
return nil, err
}
return secret, nil
},
},
"setPipelineCloneCredential": &graphql.Field{
Type: pipelineType,
Description: "Set the CloneCredential used by a pipeline to clone the source repo",
Args: graphql.FieldConfigArgument{
"cloneCredentialId": &graphql.ArgumentConfig{
Type: graphql.String, Type: graphql.String,
}, },
"pipelineId": &graphql.ArgumentConfig{ "pipelineId": &graphql.ArgumentConfig{
@@ -424,19 +503,19 @@ func createSchema(db database.Database) (graphql.Schema, error) {
return nil, err return nil, err
} }
if credentialIdVal, ok := params.Args["credentialId"]; ok { if cloneCredentialIdVal, ok := params.Args["cloneCredentialId"]; ok {
credentialId, err := uuid.Parse(credentialIdVal.(string)) cloneCredentialId, err := uuid.Parse(cloneCredentialIdVal.(string))
if err != nil { if err != nil {
return nil, err return nil, err
} }
pipeline, err := db.SetPipelineCredential(pipelineId, &credentialId) pipeline, err := db.SetPipelineCloneCredential(pipelineId, &cloneCredentialId)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return pipeline, nil return pipeline, nil
} else { } else {
pipeline, err := db.SetPipelineCredential(pipelineId, nil) pipeline, err := db.SetPipelineCloneCredential(pipelineId, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -445,6 +524,76 @@ func createSchema(db database.Database) (graphql.Schema, error) {
}, },
}, },
"addSecretToPipeline": &graphql.Field{
Type: pipelineType,
Description: "Allow a secret to be accessed by a pipeline.",
Args: graphql.FieldConfigArgument{
"secretId": &graphql.ArgumentConfig{
Type: graphql.String,
},
"pipelineId": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
secretId, err := uuid.Parse(params.Args["secretId"].(string))
if err != nil {
return nil, err
}
pipelineId, err := uuid.Parse(params.Args["pipelineId"].(string))
if err != nil {
return nil, err
}
err = db.AssignSecretToPipeline(pipelineId, secretId)
if err != nil {
return nil, err
}
pipeline, err := db.GetPipelineById(pipelineId)
if err != nil {
return nil, err
}
return pipeline, nil
},
},
"removeSecretFromPipeline": &graphql.Field{
Type: pipelineType,
Description: "Remove a pipeline's access to a secret.",
Args: graphql.FieldConfigArgument{
"secretId": &graphql.ArgumentConfig{
Type: graphql.String,
},
"pipelineId": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
secretId, err := uuid.Parse(params.Args["secretId"].(string))
if err != nil {
return nil, err
}
pipelineId, err := uuid.Parse(params.Args["pipelineId"].(string))
if err != nil {
return nil, err
}
err = db.RemoveSecretFromPipeline(pipelineId, secretId)
if err != nil {
return nil, err
}
pipeline, err := db.GetPipelineById(pipelineId)
if err != nil {
return nil, err
}
return pipeline, nil
},
},
}, },
}) })
+24 -5
View File
@@ -95,7 +95,7 @@ CREATE TABLE version (
); );
CREATE TABLE credentials ( CREATE TABLE clone_credentials (
id UUID PRIMARY KEY, id UUID PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
type TEXT NOT NULL, type TEXT NOT NULL,
@@ -108,11 +108,30 @@ CREATE TABLE pipelines (
name TEXT NOT NULL, name TEXT NOT NULL,
url TEXT NOT NULL, url TEXT NOT NULL,
poll_interval INTEGER, poll_interval INTEGER,
credential UUID DEFAULT NULL, clone_credential UUID DEFAULT NULL,
CONSTRAINT fk_credential CONSTRAINT fk_clone_credential
FOREIGN KEY(credential) FOREIGN KEY(clone_credential)
REFERENCES credentials(id) REFERENCES clone_credentials(id)
);
CREATE TABLE secrets (
id UUID PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
secret TEXT NOT NULL
);
CREATE TABLE pipeline_secret_mappings (
pipeline UUID NOT NULL,
secret UUID NOT NULL,
CONSTRAINT fk_pipeline
FOREIGN KEY(pipeline)
REFERENCES pipelines(id),
CONSTRAINT fk_secret
FOREIGN KEY(secret)
REFERENCES secrets(id)
); );
CREATE TABLE webhooks ( CREATE TABLE webhooks (
+144 -19
View File
@@ -10,7 +10,7 @@ import (
func (db *Database) GetPipelines() ([]Pipeline, error) { func (db *Database) GetPipelines() ([]Pipeline, error) {
query := ` query := `
SELECT id, name, url, poll_interval, credential SELECT id, name, url, poll_interval, clone_credential
FROM pipelines;` FROM pipelines;`
pipelines := make([]Pipeline, 0) pipelines := make([]Pipeline, 0)
@@ -24,7 +24,7 @@ FROM pipelines;`
for rows.Next() { for rows.Next() {
var pipeline Pipeline var pipeline Pipeline
var idStr string var idStr string
if err := rows.Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.Credential); err != nil { if err := rows.Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.CloneCredential); err != nil {
return pipelines, err return pipelines, err
} }
@@ -58,7 +58,7 @@ WHERE id=$1;`
func (db *Database) CreatePipeline(name string, url string, pollInterval int, credential *uuid.UUID) (Pipeline, error) { func (db *Database) CreatePipeline(name string, url string, pollInterval int, credential *uuid.UUID) (Pipeline, error) {
query := ` query := `
INSERT INTO pipelines (id, name, url, poll_interval, credential) INSERT INTO pipelines (id, name, url, poll_interval, clone_credential)
VALUES (uuid_generate_v4(), $1, $2, $3, $4) VALUES (uuid_generate_v4(), $1, $2, $3, $4)
RETURNING id, name, url, poll_interval;` RETURNING id, name, url, poll_interval;`
@@ -77,12 +77,12 @@ RETURNING id, name, url, poll_interval;`
return pipeline, nil return pipeline, nil
} }
func (db *Database) SetPipelineCredential(pipelineId uuid.UUID, credentialId *uuid.UUID) (Pipeline, error) { func (db *Database) SetPipelineCloneCredential(pipelineId uuid.UUID, credentialId *uuid.UUID) (Pipeline, error) {
query := ` query := `
UPDATE pipelines UPDATE pipelines
SET credential=$1 SET clone_credential=$1
WHERE id=$2 WHERE id=$2
RETURNING name, url, poll_interval, credential;` RETURNING name, url, poll_interval, clone_credential;`
pipeline := Pipeline{ pipeline := Pipeline{
Id: pipelineId, Id: pipelineId,
@@ -90,7 +90,7 @@ RETURNING name, url, poll_interval, credential;`
err := db.Conn.QueryRow(context.Background(), err := db.Conn.QueryRow(context.Background(),
query, credentialId, pipelineId).Scan( query, credentialId, pipelineId).Scan(
&pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.Credential, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.CloneCredential,
) )
if err != nil { if err != nil {
return pipeline, fmt.Errorf("Could not add credential to pipeline: %w", err) return pipeline, fmt.Errorf("Could not add credential to pipeline: %w", err)
@@ -104,7 +104,7 @@ func (db *Database) RemovePipelineCredential(pipelineId uuid.UUID) (Pipeline, er
UPDATE pipelines UPDATE pipelines
SET credential=null SET credential=null
WHERE id=$1 WHERE id=$1
RETURNING name, url, poll_interval, credential;` RETURNING name, url, poll_interval, clone_credential;`
pipeline := Pipeline{ pipeline := Pipeline{
Id: pipelineId, Id: pipelineId,
@@ -112,7 +112,7 @@ RETURNING name, url, poll_interval, credential;`
err := db.Conn.QueryRow(context.Background(), err := db.Conn.QueryRow(context.Background(),
query, pipelineId).Scan( query, pipelineId).Scan(
&pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.Credential, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.CloneCredential,
) )
if err != nil { if err != nil {
return pipeline, fmt.Errorf("Could not add credential to pipeline: %w", err) return pipeline, fmt.Errorf("Could not add credential to pipeline: %w", err)
@@ -194,13 +194,13 @@ RETURNING id, server_type, secret, pipeline;`
return webhook, nil return webhook, nil
} }
func (db *Database) CreateCredential(name string, credentialtype CredentialType, username string, secret string) (Credential, error) { func (db *Database) CreateCredential(name string, credentialtype CloneCredentialType, username string, secret string) (CloneCredential, error) {
query := ` query := `
INSERT INTO credentials (id, name, type, username, secret) INSERT INTO clone_credentials (id, name, type, username, secret)
VALUES(uuid_generate_v4(), $1, $2, $3, $4) VALUES(uuid_generate_v4(), $1, $2, $3, $4)
RETURNING id, name, type, username, secret;` RETURNING id, name, type, username, secret;`
credential := Credential{} credential := CloneCredential{}
var idStr string var idStr string
err := db.Conn.QueryRow( err := db.Conn.QueryRow(
context.Background(), context.Background(),
@@ -224,15 +224,15 @@ RETURNING id, name, type, username, secret;`
return credential, nil return credential, nil
} }
func (db *Database) GetCredentialById(id uuid.UUID) (Credential, error) { func (db *Database) GetCloneCredentialById(id uuid.UUID) (CloneCredential, error) {
query := ` query := `
SELECT name, type, username, secret SELECT name, type, username, secret
FROM credentials FROM clone_credentials
WHERE id=$1;` WHERE id=$1;`
log.Debugf("requested credential with id %v", id) log.Debugf("requested credential with id %v", id)
credential := Credential{ credential := CloneCredential{
Id: id, Id: id,
} }
@@ -244,12 +244,12 @@ WHERE id=$1;`
return credential, nil return credential, nil
} }
func (db *Database) GetCredentials() ([]Credential, error) { func (db *Database) GetCredentials() ([]CloneCredential, error) {
query := ` query := `
SELECT id, name, type, username, secret SELECT id, name, type, username, secret
FROM credentials;` FROM clone_credentials;`
credentials := make([]Credential, 0) credentials := make([]CloneCredential, 0)
rows, err := db.Conn.Query(context.Background(), query) rows, err := db.Conn.Query(context.Background(), query)
if err != nil { if err != nil {
@@ -258,7 +258,7 @@ FROM credentials;`
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
var credential Credential var credential CloneCredential
var idStr string var idStr string
if err := rows.Scan(&idStr, &credential.Name, &credential.Type, &credential.Username, &credential.Secret); err != nil { if err := rows.Scan(&idStr, &credential.Name, &credential.Type, &credential.Username, &credential.Secret); err != nil {
return credentials, err return credentials, err
@@ -395,3 +395,128 @@ func (db *Database) UpdatePipelineRefs(pipelineId uuid.UUID, refsMap map[string]
log.Debugf("copyCount: %v", copyCount) log.Debugf("copyCount: %v", copyCount)
return nil return nil
} }
func (db *Database) GetSecrets() ([]Secret, error) {
query := `
SELECT id, name, secret
FROM secrets;`
secrets := make([]Secret, 0)
rows, err := db.Conn.Query(context.Background(), query)
if err != nil {
return secrets, fmt.Errorf("Could not query database for secrets: %w", err)
}
defer rows.Close()
for rows.Next() {
var secret Secret
var idStr string
if err := rows.Scan(&idStr, &secret.Name, &secret.Secret); err != nil {
return secrets, err
}
secret.Id, err = uuid.Parse(idStr)
if err != nil {
return secrets, err
}
secrets = append(secrets, secret)
}
return secrets, nil
}
func (db *Database) GetSecretById(id uuid.UUID) (Secret, error) {
query := `
SELECT id, name, secret
FROM secrets
WHERE id=$1;`
secret := Secret{
Id: id,
}
err := db.Conn.QueryRow(context.Background(), query, id).Scan(&secret.Name, &secret.Secret)
if err != nil {
return secret, fmt.Errorf("Could not query database for secret with id %v: %w", id.String(), err)
}
return secret, nil
}
func (db *Database) CreateSecret(name string, secret string) (Secret, error) {
// TODO: we need to validate that we can convert the name to a valid environment variable
query := `
INSERT INTO secrets (id, name, secret)
VALUES (uuid_generate_v4(), $1, $2)
RETURNING id, name, secret;`
s := Secret{}
var idStr string
err := db.Conn.QueryRow(context.Background(), query, name, secret).Scan(&idStr, &s.Name, &s.Secret)
if err != nil {
return s, fmt.Errorf("Could not create secret: %w", err)
}
s.Id, err = uuid.Parse(idStr)
if err != nil {
return s, fmt.Errorf("Could not parse UUID generated by DB: %w", err)
}
return s, nil
}
func (db *Database) AssignSecretToPipeline(pipelineId uuid.UUID, secretId uuid.UUID) error {
query := `
INSERT INTO pipeline_secret_mappings (pipeline, secret)
VALUES ($1, $2);`
_, err := db.Conn.Exec(context.Background(), query, pipelineId, secretId)
return err
}
func (db *Database) RemoveSecretFromPipeline(pipelineId uuid.UUID, secretId uuid.UUID) error {
// TODO: implement this
return fmt.Errorf("Not implemented")
}
func (db *Database) GetSecretsForPipeline(pipelineId uuid.UUID) ([]Secret, error) {
query := `
SELECT
secrets.id, secrets.name, secrets.secret
FROM
secrets INNER JOIN pipeline_secret_mappings
ON secrets.id = pipeline_secret_mappings.secret
WHERE
pipeline_secret_mappings.pipeline=$1
;`
secrets := make([]Secret, 0)
rows, err := db.Conn.Query(context.Background(), query, pipelineId)
if err != nil {
return secrets, fmt.Errorf("Could not get secrets for pipeline with id \"%v\": %w", pipelineId, err)
}
defer rows.Close()
for rows.Next() {
var secret Secret
var idStr string
if err := rows.Scan(
&idStr,
&secret.Name,
&secret.Secret,
); err != nil {
return secrets, err
}
secret.Id, err = uuid.Parse(idStr)
if err != nil {
return secrets, err
}
secrets = append(secrets, secret)
}
return secrets, nil
}
+17 -6
View File
@@ -6,17 +6,17 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
type CredentialType string type CloneCredentialType string
const ( const (
USER_PASS CredentialType = "USER_PASS" USER_PASS CloneCredentialType = "USER_PASS"
SSH_KEY CredentialType = "SSH_KEY" SSH_KEY CloneCredentialType = "SSH_KEY"
) )
type Credential struct { type CloneCredential struct {
Id uuid.UUID Id uuid.UUID
Name string Name string
Type CredentialType Type CloneCredentialType
Username string Username string
Secret string Secret string
} }
@@ -26,7 +26,18 @@ type Pipeline struct {
Name string Name string
Url string Url string
PollInterval int PollInterval int
Credential *uuid.UUID CloneCredential *uuid.UUID
}
type Secret struct {
Id uuid.UUID
Name string
Secret string
}
type PipelineSecretMapping struct {
Pipeline uuid.UUID
Secret uuid.UUID
} }
type WebhookSender string type WebhookSender string
+24 -2
View File
@@ -7,6 +7,7 @@ import (
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
@@ -54,8 +55,8 @@ func ExecutePipeline(pe PipelineExecution, db database.Database, pipelineConf co
var auth transport.AuthMethod var auth transport.AuthMethod
if pe.Pipeline.Credential != nil { if pe.Pipeline.CloneCredential != nil {
credential, err := db.GetCredentialById(*pe.Pipeline.Credential) credential, err := db.GetCloneCredentialById(*pe.Pipeline.CloneCredential)
if err != nil { if err != nil {
log.Errorf("could not get credenital from db: %v", err) log.Errorf("could not get credenital from db: %v", err)
return return
@@ -154,6 +155,27 @@ func ExecutePipeline(pe PipelineExecution, db database.Database, pipelineConf co
) )
} }
env := make([]string, 0)
// set cursorius environment variables
env = append(env, []string{
fmt.Sprintf("RUNID=%v", pe.Run.Id),
"CURSORIUS_SRC_DIR=/cursorius/src",
fmt.Sprintf("CUROSRIUS_SERVER_URL=%v", pipelineConf.AccessURL),
}...)
// load secrets into environment
secrets, err := db.GetSecretsForPipeline(pe.Pipeline.Id)
if err != nil {
log.Errorf("Could not get secrets for pipeline", err)
return
}
for _, secret := range secrets {
// TODO: this doesn't validate either of these strings
env = append(env, fmt.Sprintf("%v=%v", strings.ToUpper(secret.Name), secret.Secret))
}
resp, err := cli.ContainerCreate(ctx, resp, err := cli.ContainerCreate(ctx,
&container.Config{ &container.Config{
Image: imageName, Image: imageName,