Skip to content
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
5 changes: 3 additions & 2 deletions charts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ their default values.
| `marbleInjector.namespaceSelector` | object | NamespaceSelector to trigger marble-injector mutation, See the [K8S documentation](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) for more information | `{}` |
| `nodeSelector` | object | NodeSelector section, See the [K8S documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) for more information | `{"beta.kubernetes.io/os": "linux"}` |
| `tolerations` | object | Tolerations section, See the [K8S documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) for more information | `{key:"sgx.intel.com/epc",operator:"Exists",effect:"NoSchedule"}` |
| `dcap.pccsUrl` | string | URL of the PCCS | `"https://global.acccache.azure.net/sgx/certification/v4/"` |
| `dcap.useSecureCert` | string | Whether or not the TLS certificate of the PCCS should be verified | `"TRUE"` |
| `dcap.qcnlConfig` | string | Inline defined QCNL configuration. If set, this configuration is used instead of the one created from `dcap.pccsUrl` and `dcap.useSecureCert` | `""` |
| `dcap.pccsUrl` | string | URL of the PCCS. Only used if `dcap.qcnlConfig` is not set | `"https://global.acccache.azure.net/sgx/certification/v4/"` |
| `dcap.useSecureCert` | string | Whether or not the TLS certificate of the PCCS should be verified. Only used if `dcap.qcnlConfig` is not set | `true` |

## Add new version (maintainers)

Expand Down
15 changes: 13 additions & 2 deletions charts/templates/sgx_qcnl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ metadata:
{{ .Values.global.coordinatorComponentLabel }}: dcap-config
{{ .Values.global.coordinatorNamespaceLabel }}: {{ .Release.Namespace }}
data:
{{- if .Values.dcap.qcnlConfig }}
sgx_default_qcnl.conf: |-
{{ .Values.dcap.qcnlConfig | indent 4 }}
{{- else }}
sgx_default_qcnl.conf: |
PCCS_URL={{ .Values.dcap.pccsUrl }}
USE_SECURE_CERT={{ .Values.dcap.useSecureCert }}
{
"pccs_url": "{{ .Values.dcap.pccsUrl }}",
{{- if kindIs "bool" .Values.dcap.useSecureCert }}
"use_secure_cert": {{ .Values.dcap.useSecureCert }}
{{- else }}
"use_secure_cert": {{ eq (lower (toString .Values.dcap.useSecureCert)) "true" }}
{{- end }}
}
{{- end}}
{{ end }}
5 changes: 4 additions & 1 deletion charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,8 @@ nodeSelector:

# DCAP configuration settings
dcap:
# Set to use an inline defined QCNL configuration
qcnlConfig: ""
# If qcnlConfig is not set, the default values below are used to create a config file
pccsUrl: "https://global.acccache.azure.net/sgx/certification/v4/"
useSecureCert: "TRUE"
useSecureCert: true
15 changes: 13 additions & 2 deletions cli/internal/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,19 @@ marblerun install --dcap-pccs-url https://pccs.example.com/sgx/certification/v4/
cmd.Flags().String("version", "", "Version of the Coordinator to install, latest by default")
cmd.Flags().String("resource-key", "", "Resource providing SGX, different depending on used device plugin. Use this to set tolerations/resources if your device plugin is not supported by MarbleRun")
cmd.Flags().String("dcap-qpl", "azure", `Quote provider library to use by the Coordinator. One of {"azure", "intel"}`)
cmd.Flags().String("dcap-pccs-url", "https://global.acccache.azure.net/sgx/certification/v4/", "Provisioning Certificate Caching Service (PCCS) server address. Defaults to Azure PCCS.")
cmd.Flags().String("dcap-secure-cert", "TRUE", "To accept insecure HTTPS certificate from the PCCS, set this option to FALSE")
cmd.Flags().String("dcap-qcnl-config-file", "", "Path to a custom QCNL configuration file. Mutually exclusive with \"--dcap-pccs-url\" and \"--dcap-secure-cert\".")
cmd.Flags().String("dcap-pccs-url", "https://global.acccache.azure.net/sgx/certification/v4/", "Provisioning Certificate Caching Service (PCCS) server address. Defaults to Azure PCCS. Mutually exclusive with \"--dcap-qcnl-config-file\"")
cmd.Flags().String("dcap-secure-cert", "TRUE", "To accept insecure HTTPS certificate from the PCCS, set this option to FALSE. Mutually exclusive with \"--dcap-qcnl-config-file\"")
cmd.Flags().String("enterprise-access-token", "", "Access token for Enterprise Coordinator. Leave empty for default installation")
cmd.Flags().Bool("simulation", false, "Set MarbleRun to start in simulation mode")
cmd.Flags().Bool("disable-auto-injection", false, "Install MarbleRun without auto-injection webhook")
cmd.Flags().Bool("wait", false, "Wait for MarbleRun installation to complete before returning")
cmd.Flags().Int("mesh-server-port", 2001, "Set the mesh server port. Needs to be configured to the same port as in the data-plane marbles")
cmd.Flags().Int("client-server-port", 4433, "Set the client server port. Needs to be configured to the same port as in your client tool stack")

cmd.MarkFlagsMutuallyExclusive("dcap-qcnl-config-file", "dcap-pccs-url")
cmd.MarkFlagsMutuallyExclusive("dcap-qcnl-config-file", "dcap-secure-cert")

must(cmd.Flags().MarkDeprecated("dcap-qpl", "All platforms use the same QPL now. Use --dcap-pccs-url to configure the PCCS server address."))

return cmd
Expand Down Expand Up @@ -116,6 +120,7 @@ func cliInstall(cmd *cobra.Command, helmClient *helm.Client, kubeClient kubernet
values, err := helm.UpdateValues(
helm.Options{
Hostname: flags.hostname,
QCNLConfigFile: flags.qcnlConfigFile,
PCCSURL: flags.pccsURL,
UseSecureCert: flags.useSecureCert,
AccessToken: flags.accessToken,
Expand Down Expand Up @@ -275,6 +280,7 @@ type installFlags struct {
hostname []string
version string
resourceKey string
qcnlConfigFile string
pccsURL string
useSecureCert string
accessToken string
Expand Down Expand Up @@ -302,6 +308,10 @@ func parseInstallFlags(cmd *cobra.Command) (installFlags, error) {
if err != nil {
return installFlags{}, err
}
qcnlConfigFile, err := cmd.Flags().GetString("dcap-qcnl-config-file")
if err != nil {
return installFlags{}, err
}
pccsURL, err := cmd.Flags().GetString("dcap-pccs-url")
if err != nil {
return installFlags{}, err
Expand Down Expand Up @@ -344,6 +354,7 @@ func parseInstallFlags(cmd *cobra.Command) (installFlags, error) {
hostname: hostname,
version: version,
resourceKey: resourceKey,
qcnlConfigFile: qcnlConfigFile,
pccsURL: pccsURL,
useSecureCert: useSecureCert,
accessToken: accessToken,
Expand Down
72 changes: 45 additions & 27 deletions cli/internal/helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
// Options contains the values to set in the helm chart.
type Options struct {
Hostname []string
QCNLConfigFile string
PCCSURL string
UseSecureCert string
AccessToken string
Expand Down Expand Up @@ -92,12 +93,13 @@ func (c *Client) GetChart(chartPath, version string) (*chart.Chart, error) {
}

// UpdateValues merges the provided options with the default values of the chart.
func UpdateValues(options Options, chartValues map[string]interface{}) (map[string]interface{}, error) {
func UpdateValues(options Options, chartValues map[string]any) (map[string]any, error) {
fileValues := []string{}
stringValues := []string{}
stringValues = append(stringValues, fmt.Sprintf("coordinator.meshServerPort=%d", options.CoordinatorGRPCPort))
stringValues = append(stringValues, fmt.Sprintf("coordinator.clientServerPort=%d", options.CoordinatorRESTPort))

if coordinatorOpts, ok := chartValues["coordinator"].(map[string]interface{}); ok {
if coordinatorOpts, ok := chartValues["coordinator"].(map[string]any); ok {
if existingHostname, ok := coordinatorOpts["hostname"].(string); ok && existingHostname != "" {
options.Hostname = append(options.Hostname, existingHostname)
}
Expand All @@ -113,32 +115,36 @@ func UpdateValues(options Options, chartValues map[string]interface{}) (map[stri
fmt.Sprintf("dcap=%s", "null"),
)
} else {
stringValues = append(stringValues,
fmt.Sprintf("dcap.pccsUrl=%s", options.PCCSURL),
fmt.Sprintf("dcap.useSecureCert=%s", options.UseSecureCert),
)
if options.QCNLConfigFile != "" {
fileValues = append(fileValues, fmt.Sprintf("dcap.qcnlConfig=%s", options.QCNLConfigFile))
} else {
stringValues = append(stringValues,
fmt.Sprintf("dcap.pccsUrl=%s", options.PCCSURL),
fmt.Sprintf("dcap.useSecureCert=%s", options.UseSecureCert),
)
}

// Helms value merge function will overwrite any preset values for "tolerations" if we set new ones here
// To avoid this we set the new toleration for "resourceKey" and copy all preset tolerations
needToleration := true
idx := 0
for _, toleration := range chartValues["tolerations"].([]interface{}) {
if key, ok := toleration.(map[string]interface{})["key"]; ok {
for _, toleration := range chartValues["tolerations"].([]any) {
if key, ok := toleration.(map[string]any)["key"]; ok {
if key == options.SGXResourceKey {
needToleration = false
}
stringValues = append(stringValues, fmt.Sprintf("tolerations[%d].key=%v", idx, key))
}
if operator, ok := toleration.(map[string]interface{})["operator"]; ok {
if operator, ok := toleration.(map[string]any)["operator"]; ok {
stringValues = append(stringValues, fmt.Sprintf("tolerations[%d].operator=%v", idx, operator))
}
if effect, ok := toleration.(map[string]interface{})["effect"]; ok {
if effect, ok := toleration.(map[string]any)["effect"]; ok {
stringValues = append(stringValues, fmt.Sprintf("tolerations[%d].effect=%v", idx, effect))
}
if value, ok := toleration.(map[string]interface{})["value"]; ok {
if value, ok := toleration.(map[string]any)["value"]; ok {
stringValues = append(stringValues, fmt.Sprintf("tolerations[%d].value=%v", idx, value))
}
if tolerationSeconds, ok := toleration.(map[string]interface{})["tolerationSeconds"]; ok {
if tolerationSeconds, ok := toleration.(map[string]any)["tolerationSeconds"]; ok {
stringValues = append(stringValues, fmt.Sprintf("tolerations[%d].tolerationSeconds=%v", idx, tolerationSeconds))
}
idx++
Expand All @@ -154,7 +160,7 @@ func UpdateValues(options Options, chartValues map[string]interface{}) (map[stri

// Configure enterprise access token
if options.AccessToken != "" {
coordinatorCfg, ok := chartValues["coordinator"].(map[string]interface{})
coordinatorCfg, ok := chartValues["coordinator"].(map[string]any)
if !ok {
return nil, errors.New("coordinator not found in chart values")
}
Expand All @@ -179,12 +185,24 @@ func UpdateValues(options Options, chartValues map[string]interface{}) (map[stri
stringValues = append(stringValues, fmt.Sprintf("marbleInjector.resourceKey=%s", options.SGXResourceKey))
}

finalValues := map[string]interface{}{}
finalValues := map[string]any{}
for _, val := range stringValues {
if err := strvals.ParseInto(val, finalValues); err != nil {
return nil, fmt.Errorf("parsing value %q into final values: %w", val, err)
}
}
for _, val := range fileValues {
runeReader := func(rs []rune) (any, error) {
file, err := os.ReadFile(string(rs))
if err != nil {
return nil, fmt.Errorf("reading file %q: %w", string(rs), err)
}
return string(file), nil
}
if err := strvals.ParseIntoFile(val, finalValues, runeReader); err != nil {
return nil, fmt.Errorf("parsing file value %q into final values: %w", val, err)
}
}

if !options.SimulationMode {
setSGXValues(options.SGXResourceKey, finalValues, chartValues)
Expand All @@ -194,7 +212,7 @@ func UpdateValues(options Options, chartValues map[string]interface{}) (map[stri
}

// Install installs MarbleRun using the provided chart and values.
func (c *Client) Install(ctx context.Context, wait bool, chart *chart.Chart, values map[string]interface{}) error {
func (c *Client) Install(ctx context.Context, wait bool, chart *chart.Chart, values map[string]any) error {
installer := action.NewInstall(c.config)
installer.Namespace = c.namespace
installer.ReleaseName = release
Expand Down Expand Up @@ -277,45 +295,45 @@ func (c *Client) getRepo(name string, url string) error {

// setSGXValues sets the needed values for the coordinator as a map[string]interface.
// strvals can't parse keys which include dots, e.g. setting as a resource limit key "sgx.intel.com/epc" will lead to errors.
func setSGXValues(resourceKey string, values, chartValues map[string]interface{}) {
values["coordinator"].(map[string]interface{})["resources"] = map[string]interface{}{
"limits": map[string]interface{}{},
"requests": map[string]interface{}{},
func setSGXValues(resourceKey string, values, chartValues map[string]any) {
values["coordinator"].(map[string]any)["resources"] = map[string]any{
"limits": map[string]any{},
"requests": map[string]any{},
}

var needNewLimit bool
limit := k8sutil.GetEPCResourceLimit(resourceKey)

// remove all previously set sgx resource limits
if presetLimits, ok := chartValues["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["limits"].(map[string]interface{}); ok {
if presetLimits, ok := chartValues["coordinator"].(map[string]any)["resources"].(map[string]any)["limits"].(map[string]any); ok {
for oldResourceKey := range presetLimits {
// Make sure the key we delete is an unwanted sgx resource and not a custom resource or common resource (cpu, memory, etc.)
if needsDeletion(oldResourceKey, resourceKey) {
values["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["limits"].(map[string]interface{})[oldResourceKey] = nil
values["coordinator"].(map[string]any)["resources"].(map[string]any)["limits"].(map[string]any)[oldResourceKey] = nil
needNewLimit = true
}
}
}

// remove all previously set sgx resource requests
if presetLimits, ok := chartValues["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{}); ok {
if presetLimits, ok := chartValues["coordinator"].(map[string]any)["resources"].(map[string]any)["requests"].(map[string]any); ok {
for oldResourceKey := range presetLimits {
if needsDeletion(oldResourceKey, resourceKey) {
values["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})[oldResourceKey] = nil
values["coordinator"].(map[string]any)["resources"].(map[string]any)["requests"].(map[string]any)[oldResourceKey] = nil
needNewLimit = true
}
}
}

// Set the new sgx resource limit, kubernetes will automatically set a resource request equal to the limit
if needNewLimit {
values["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["limits"].(map[string]interface{})[resourceKey] = limit
values["coordinator"].(map[string]any)["resources"].(map[string]any)["limits"].(map[string]any)[resourceKey] = limit
}

// Make sure provision and enclave bit is set if the Intel plugin is used
if resourceKey == k8sutil.IntelEpc.String() {
values["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["limits"].(map[string]interface{})[k8sutil.IntelProvision.String()] = 1
values["coordinator"].(map[string]interface{})["resources"].(map[string]interface{})["limits"].(map[string]interface{})[k8sutil.IntelEnclave.String()] = 1
values["coordinator"].(map[string]any)["resources"].(map[string]any)["limits"].(map[string]any)[k8sutil.IntelProvision.String()] = 1
values["coordinator"].(map[string]any)["resources"].(map[string]any)["limits"].(map[string]any)[k8sutil.IntelEnclave.String()] = 1
}
}

Expand Down Expand Up @@ -351,4 +369,4 @@ func keyInList(key string, list []string) bool {
return false
}

func nopLog(_ string, _ ...interface{}) {}
func nopLog(_ string, _ ...any) {}
5 changes: 3 additions & 2 deletions docs/docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ marblerun install --dcap-pccs-url https://pccs.example.com/sgx/certification/v4/

```
--client-server-port int Set the client server port. Needs to be configured to the same port as in your client tool stack (default 4433)
--dcap-pccs-url string Provisioning Certificate Caching Service (PCCS) server address. Defaults to Azure PCCS. (default "https://global.acccache.azure.net/sgx/certification/v4/")
--dcap-secure-cert string To accept insecure HTTPS certificate from the PCCS, set this option to FALSE (default "TRUE")
--dcap-pccs-url string Provisioning Certificate Caching Service (PCCS) server address. Defaults to Azure PCCS. Mutually exclusive with "--dcap-qcnl-config-file" (default "https://global.acccache.azure.net/sgx/certification/v4/")
--dcap-qcnl-config-file string Path to a custom QCNL configuration file. Mutually exclusive with "--dcap-pccs-url" and "--dcap-secure-cert".
--dcap-secure-cert string To accept insecure HTTPS certificate from the PCCS, set this option to FALSE. Mutually exclusive with "--dcap-qcnl-config-file" (default "TRUE")
--disable-auto-injection Install MarbleRun without auto-injection webhook
--domain strings Sets additional DNS names and IPs for the Coordinator TLS certificate
--enterprise-access-token string Access token for Enterprise Coordinator. Leave empty for default installation
Expand Down
2 changes: 1 addition & 1 deletion util/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func MustGenerateTestMarbleCredentials() (cert *x509.Certificate, csrRaw []byte,
panic(err)
}
csrRaw = csr.Raw
return
return cert, csrRaw, privk
}

// GenerateCert generates a new self-signed certificate associated key-pair.
Expand Down