Skip to content

[server] Load auth-pki into server config - WEB-100 #17214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions components/server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type Config = Omit<
| "linkedInSecretsFile"
| "licenseFile"
| "patSigningKeyFile"
| "auth"
> & {
hostUrl: GitpodHostUrl;
workspaceDefaults: WorkspaceDefaults;
Expand All @@ -44,6 +45,20 @@ export type Config = Omit<
// Absolute file path pointing to a file which contains admin credentials, encoded as JSON.
credentialsPath: string;
};

auth: {
// Public/Private key for signing authenticated sessions
pki: {
signing: {
privateKey: string;
publicKey: string;
};
validating: {
privateKey: string;
publicKey: string;
}[];
};
};
};

export interface WorkspaceDefaults {
Expand Down Expand Up @@ -244,6 +259,20 @@ export interface ConfigSerialized {
* This is the same signing key used by Public API
*/
patSigningKeyFile?: string;

auth: {
pki: AuthPKIConfig;
};
}

export interface AuthPKIConfig {
signing: KeyPair;
validating?: KeyPair[];
}

export interface KeyPair {
publicKeyPath: string;
privateKeyPath: string;
}

export namespace ConfigFile {
Expand Down Expand Up @@ -346,6 +375,18 @@ export namespace ConfigFile {
}
}

const authPKI: Config["auth"]["pki"] = {
signing: {
privateKey: fs.readFileSync(filePathTelepresenceAware(config.auth.pki.signing.privateKeyPath), "utf-8"),
publicKey: fs.readFileSync(filePathTelepresenceAware(config.auth.pki.signing.publicKeyPath), "utf-8"),
},
validating:
config.auth.pki.validating?.map((keypair) => ({
privateKey: fs.readFileSync(filePathTelepresenceAware(keypair.privateKeyPath), "utf-8"),
publicKey: fs.readFileSync(filePathTelepresenceAware(keypair.publicKeyPath), "utf-8"),
})) || [],
};

return {
...config,
hostUrl,
Expand All @@ -368,6 +409,9 @@ export namespace ConfigFile {
...config.admin,
credentialsPath: config.admin.credentialsPath,
},
auth: {
pki: authPKI,
},
};
}
}
35 changes: 35 additions & 0 deletions install/installer/pkg/components/server/authpki.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ package server
import (
"fmt"
"math"
"path"
"time"

"github.com/gitpod-io/gitpod/installer/pkg/common"

certmanagerv1 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
Expand Down Expand Up @@ -56,3 +58,36 @@ func authPKI(ctx *common.RenderContext) ([]runtime.Object, error) {
},
}, nil
}

func getAuthPKI() ([]corev1.Volume, []corev1.VolumeMount, AuthPKIConfig) {

dir := "/secrets/auth-pki"
signingDir := path.Join(dir, "signing")

volumes := []corev1.Volume{
{
Name: "auth-pki-signing",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: AuthPKISecretName,
},
},
},
}

mounts := []corev1.VolumeMount{
{
Name: "auth-pki-signing",
MountPath: signingDir,
ReadOnly: true,
},
}

cfg := AuthPKIConfig{
Signing: KeyPair{
PrivateKeyPath: path.Join(signingDir, "tls.key"),
PublicKeyPath: path.Join(signingDir, "tls.crt"),
},
}
return volumes, mounts, cfg
}
5 changes: 5 additions & 0 deletions install/installer/pkg/components/server/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) {

_, _, adminCredentialsPath := getAdminCredentials()

_, _, authPKI := getAuthPKI()

// todo(sje): all these values are configurable
scfg := ConfigSerialized{
Version: ctx.VersionManifest.Version,
Expand Down Expand Up @@ -297,6 +299,9 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) {
CredentialsPath: adminCredentialsPath,
},
ShowSetupModal: showSetupModal,
Auth: AuthConfig{
PKI: authPKI,
},
}

fc, err := common.ToJSONString(scfg)
Expand Down
10 changes: 10 additions & 0 deletions install/installer/pkg/components/server/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestConfigMap(t *testing.T) {
JWTSecret string
SessionSecret string
GitHubApp experimental.GithubApp
Auth AuthConfig
}

expectation := Expectation{
Expand All @@ -52,6 +53,14 @@ func TestConfigMap(t *testing.T) {
WebhookSecret: "some-webhook-secret",
CertSecretName: "some-cert-secret-name",
},
Auth: AuthConfig{
PKI: AuthPKIConfig{
Signing: KeyPair{
PrivateKeyPath: "/secrets/auth-pki/signing/tls.key",
PublicKeyPath: "/secrets/auth-pki/signing/tls.crt",
},
},
},
}

ctx, err := common.NewRenderContext(config.Config{
Expand Down Expand Up @@ -122,6 +131,7 @@ func TestConfigMap(t *testing.T) {
WebhookSecret: config.GitHubApp.WebhookSecret,
CertSecretName: config.GitHubApp.CertSecretName,
},
Auth: config.Auth,
}

assert.Equal(t, expectation, actual)
Expand Down
4 changes: 4 additions & 0 deletions install/installer/pkg/components/server/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ func deployment(ctx *common.RenderContext) ([]runtime.Object, error) {
volumes = append(volumes, adminCredentialsVolume)
volumeMounts = append(volumeMounts, adminCredentialsMount)

authPKIVolumes, authPKIMounts, _ := getAuthPKI()
volumes = append(volumes, authPKIVolumes...)
volumeMounts = append(volumeMounts, authPKIMounts...)

return []runtime.Object{
&appsv1.Deployment{
TypeMeta: common.TypeMetaDeployment,
Expand Down
70 changes: 44 additions & 26 deletions install/installer/pkg/components/server/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,33 @@ import (

// ConfigSerialized interface from components/server/src/config.ts
type ConfigSerialized struct {
Version string `json:"version"`
HostURL string `json:"hostUrl"`
InstallationShortname string `json:"installationShortname"`
DevBranch string `json:"devBranch"`
InsecureNoDomain bool `json:"insecureNoDomain"`
License string `json:"license"`
DefinitelyGpDisabled bool `json:"definitelyGpDisabled"`
EnableLocalApp bool `json:"enableLocalApp"`
DisableDynamicAuthProviderLogin bool `json:"disableDynamicAuthProviderLogin"`
MaxEnvvarPerUserCount int32 `json:"maxEnvvarPerUserCount"`
MaxConcurrentPrebuildsPerRef int32 `json:"maxConcurrentPrebuildsPerRef"`
MakeNewUsersAdmin bool `json:"makeNewUsersAdmin"`
DefaultBaseImageRegistryWhitelist []string `json:"defaultBaseImageRegistryWhitelist"`
RunDbDeleter bool `json:"runDbDeleter"`
ContentServiceAddr string `json:"contentServiceAddr"`
UsageServiceAddr string `json:"usageServiceAddr"`
IDEServiceAddr string `json:"ideServiceAddr"`
MaximumEventLoopLag float64 `json:"maximumEventLoopLag"`
VSXRegistryUrl string `json:"vsxRegistryUrl"`
ChargebeeProviderOptionsFile string `json:"chargebeeProviderOptionsFile"`
StripeSecretsFile string `json:"stripeSecretsFile"`
StripeConfigFile string `json:"stripeConfigFile"`
EnablePayment bool `json:"enablePayment"`
LinkedInSecretsFile string `json:"linkedInSecretsFile"`
PATSigningKeyFile string `json:"patSigningKeyFile"`
ShowSetupModal bool `json:"showSetupModal"`
Version string `json:"version"`
HostURL string `json:"hostUrl"`
InstallationShortname string `json:"installationShortname"`
DevBranch string `json:"devBranch"`
InsecureNoDomain bool `json:"insecureNoDomain"`
License string `json:"license"`
DefinitelyGpDisabled bool `json:"definitelyGpDisabled"`
EnableLocalApp bool `json:"enableLocalApp"`
DisableDynamicAuthProviderLogin bool `json:"disableDynamicAuthProviderLogin"`
MaxEnvvarPerUserCount int32 `json:"maxEnvvarPerUserCount"`
MaxConcurrentPrebuildsPerRef int32 `json:"maxConcurrentPrebuildsPerRef"`
MakeNewUsersAdmin bool `json:"makeNewUsersAdmin"`
DefaultBaseImageRegistryWhitelist []string `json:"defaultBaseImageRegistryWhitelist"`
RunDbDeleter bool `json:"runDbDeleter"`
ContentServiceAddr string `json:"contentServiceAddr"`
UsageServiceAddr string `json:"usageServiceAddr"`
IDEServiceAddr string `json:"ideServiceAddr"`
MaximumEventLoopLag float64 `json:"maximumEventLoopLag"`
VSXRegistryUrl string `json:"vsxRegistryUrl"`
ChargebeeProviderOptionsFile string `json:"chargebeeProviderOptionsFile"`
StripeSecretsFile string `json:"stripeSecretsFile"`
StripeConfigFile string `json:"stripeConfigFile"`
EnablePayment bool `json:"enablePayment"`
LinkedInSecretsFile string `json:"linkedInSecretsFile"`
PATSigningKeyFile string `json:"patSigningKeyFile"`
ShowSetupModal bool `json:"showSetupModal"`
Auth AuthConfig `json:"auth"`

WorkspaceHeartbeat WorkspaceHeartbeat `json:"workspaceHeartbeat"`
WorkspaceDefaults WorkspaceDefaults `json:"workspaceDefaults"`
Expand All @@ -65,6 +66,23 @@ type CodeSyncResources struct {
RevLimit int32 `json:"revLimit"`
}

type AuthConfig struct {
PKI AuthPKIConfig `json:"pki"`
}

type AuthPKIConfig struct {
// Signing KeyPair is always used to issue new auth tokens
Signing KeyPair `json:"signing"`

// Validating KeyPairs are used for checking validity only
Validating []KeyPair `json:"validating,omitempty"`
}

type KeyPair struct {
PrivateKeyPath string `json:"privateKeyPath"`
PublicKeyPath string `json:"publicKeyPath"`
}

type CodeSync struct {
RevLimit int32 `json:"revLimit"`
ContentLimit int32 `json:"contentLimit"`
Expand Down