public async void ReadDeploymentConfigFromSecret() { ISerde <DeploymentConfigInfo> serde = this.GetSerde(); var secretData = new Dictionary <string, byte[]> { ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(serde.Serialize(ValidConfigInfo1)) }; var secret = new V1Secret(data: secretData); var response = new HttpOperationResponse <V1Secret>() { Body = secret, Response = new HttpResponseMessage(HttpStatusCode.OK) }; var client = new Mock <IKubernetes>(MockBehavior.Strict); client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(DefaultSecretName, DefaultNamespace, It.IsAny <bool?>(), It.IsAny <bool?>(), null, null, It.IsAny <CancellationToken>())) .ReturnsAsync(response); var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object); var deploymentConfigInfo = await backupSource.ReadFromBackupAsync(); string returnedJson = serde.Serialize(deploymentConfigInfo); string expectedJson = serde.Serialize(ValidConfigInfo1); Assert.Equal(expectedJson, returnedJson, ignoreCase: true); client.VerifyAll(); }
public async void DeserializeFaillureReturnsEmptyConfig() { ISerde<DeploymentConfigInfo> serde = this.GetSerde(); var secretData = new Dictionary<string, byte[]> { ["backup.json"] = System.Text.Encoding.UTF8.GetBytes("{}") }; var secret = new V1Secret(data: secretData); var response = new HttpOperationResponse<V1Secret>() { Body = secret, Response = new HttpResponseMessage(HttpStatusCode.OK) }; var client = new Mock<IKubernetes>(MockBehavior.Strict); client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync( DefaultSecretName, DefaultNamespace, It.IsAny<string>(), // pretty null, // customHeaders It.IsAny<CancellationToken>())) .ReturnsAsync(response); var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object); var deploymentConfigInfo = await backupSource.ReadFromBackupAsync(); Assert.NotNull(deploymentConfigInfo); Assert.Equal(DeploymentConfigInfo.Empty, deploymentConfigInfo); client.VerifyAll(); }
private void EnsureServiceAccountToken(User user) { var groupNamespaceName = user.Spec.GetGroupNamespace(); var tokenName = $"{user.Metadata.Name}-token"; var tokens = _client.ListNamespacedSecret(groupNamespaceName, fieldSelector: $"metadata.name={tokenName}"); if (!tokens.Items.Any()) { var secret = new V1Secret { Metadata = new V1ObjectMeta { Name = tokenName, Labels = new Dictionary <string, string>() { { "kiamol", "ch20" }, }, Annotations = new Dictionary <string, string>() { { "kubernetes.io/service-account.name", user.Metadata.Name }, } }, Type = "kubernetes.io/service-account-token" }; _client.CreateNamespacedSecret(secret, groupNamespaceName); Console.WriteLine($"** Created token: {tokenName}, in group namespace: {groupNamespaceName}"); } else { Console.WriteLine($"** Token exists: {tokenName}, in group namespace: {groupNamespaceName}"); } }
public async void BackupDeploymentDoesNotThrowOnFailure() { ISerde <DeploymentConfigInfo> serde = this.GetSerde(); string expectedJson = serde.Serialize(ValidConfigInfo1); var readSecretData = new Dictionary <string, byte[]> { ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(serde.Serialize(ValidConfigInfo2)) }; var readSecret = new V1Secret(data: readSecretData); var replaceSecretData = new Dictionary <string, byte[]> { ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(expectedJson) }; var replaceSecret = new V1Secret(data: readSecretData); var readResponse = new HttpOperationResponse <V1Secret>() { Body = readSecret, Response = new HttpResponseMessage(HttpStatusCode.OK) }; var client = new Mock <IKubernetes>(MockBehavior.Strict); client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(DefaultSecretName, DefaultNamespace, It.IsAny <bool?>(), It.IsAny <bool?>(), null, null, It.IsAny <CancellationToken>())) .ReturnsAsync(readResponse); client.Setup(c => c.ReplaceNamespacedSecretWithHttpMessagesAsync(It.IsAny <V1Secret>(), DefaultSecretName, DefaultNamespace, null, null, null, null, It.IsAny <CancellationToken>())) .ThrowsAsync(new HttpOperationException("Not Permitted")); var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object); await backupSource.BackupDeploymentConfigAsync(ValidConfigInfo1); client.VerifyAll(); }
public async void BackupDeploymentConfigReplacesSecret() { ISerde<DeploymentConfigInfo> serde = this.GetSerde(); string expectedJson = serde.Serialize(ValidConfigInfo1); var readSecretData = new Dictionary<string, byte[]> { ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(serde.Serialize(ValidConfigInfo2)) }; var readSecret = new V1Secret(data: readSecretData); var replaceSecretData = new Dictionary<string, byte[]> { ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(expectedJson) }; var replaceSecret = new V1Secret(data: readSecretData); var readResponse = new HttpOperationResponse<V1Secret>() { Body = readSecret, Response = new HttpResponseMessage(HttpStatusCode.OK) }; var replaceResponse = new HttpOperationResponse<V1Secret>() { Body = replaceSecret, Response = new HttpResponseMessage(HttpStatusCode.OK) }; byte[] receivedData = default(byte[]); var client = new Mock<IKubernetes>(MockBehavior.Strict); client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync( DefaultSecretName, DefaultNamespace, It.IsAny<string>(), // pretty null, // customHeaders It.IsAny<CancellationToken>())) .ReturnsAsync(readResponse); client.Setup(c => c.ReplaceNamespacedSecretWithHttpMessagesAsync( It.IsAny<V1Secret>(), DefaultSecretName, DefaultNamespace, null, // dryRun null, // fieldmanager null, // pretty null, // customHeaders It.IsAny<CancellationToken>())) .Callback((V1Secret body, string name, string namespaceParameter, string dryRun, string fieldManager, string pretty, Dictionary<string, List<string>> customHeaders, CancellationToken cancellationToken) => { Assert.True(body.Data != null); Assert.True(body.Data.TryGetValue("backup.json", out receivedData)); }) .ReturnsAsync(replaceResponse); var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object); await backupSource.BackupDeploymentConfigAsync(ValidConfigInfo1); string backupJson = System.Text.Encoding.UTF8.GetString(receivedData); Assert.Equal(expectedJson, backupJson, ignoreCase: true); client.VerifyAll(); }
public void ReturnsFalseIfFieldsAreDifferent() { var x = new V1Secret { Metadata = new V1ObjectMeta { Annotations = new Dictionary <string, string> { [KubernetesConstants.K8sEdgeOriginalModuleId] = "Object1" }, Labels = new Dictionary <string, string> { [KubernetesConstants.K8sEdgeDeviceLabel] = "device1", [KubernetesConstants.K8sEdgeHubNameLabel] = "hostname" }, Name = "object1" }, Data = new Dictionary <string, byte[]> { [KubernetesConstants.K8sPullSecretData] = new byte[] { 1 } } }; var y = new V1Secret { Metadata = new V1ObjectMeta { Annotations = new Dictionary <string, string> { [KubernetesConstants.K8sEdgeOriginalModuleId] = "Object1" }, Labels = new Dictionary <string, string> { [KubernetesConstants.K8sEdgeDeviceLabel] = "device1", [KubernetesConstants.K8sEdgeHubNameLabel] = "hostname" }, Name = "object1" }, Data = new Dictionary <string, byte[]> { [KubernetesConstants.K8sPullSecretData] = new byte[] { 1 } } }; Assert.True(Comparer.Equals(x, y)); y.Metadata.Name = "object2"; Assert.False(Comparer.Equals(x, y)); y.Metadata.Name = "object1"; Assert.True(Comparer.Equals(x, y)); y.Metadata.Labels = new Dictionary <string, string> { ["newkey2"] = "Object1" }; Assert.False(Comparer.Equals(x, y)); }
/// <summary> /// Converts this <see cref="V1Secret"/> to a <see cref="X509Certificate2"/>. /// </summary> /// <param name="secret"> /// A <see cref="V1Secret"/> which represents a Kubernetes TLS secret. /// </param> /// <returns> /// The equivalent <see cref="X509Certificate2"/> value. /// </returns> public static X509Certificate2 AsX509Certificate2(this V1Secret secret) { EnsureTlsSecret(secret); // Both DER-encoded return(X509Certificate2.CreateFromPem( Encoding.UTF8.GetString(secret.Data[TlsCertificate]), Encoding.UTF8.GetString(secret.Data[TlsPrivateKey]))); }
/// <summary> /// Converts this <see cref="V1Secret"/> to a <see cref="SignedCms"/>. /// </summary> /// <param name="secret"> /// A <see cref="V1Secret"/> which represents CMS signed data. /// </param> /// <returns> /// The equivalent <see cref="SignedCms"/> value. /// </returns> public static SignedCms AsSignedCms(this V1Secret secret) { EnsureProvisioningProfileSecret(secret); SignedCms cms = new SignedCms(); cms.Decode(secret.Data[SignedDataContent]); return(cms); }
public Task <V1Secret> UpdatePrometheusScrapeConfigSecretAsync(V1Secret secret, CancellationToken cancellationToken) { Init(); return(_client.ReplaceNamespacedSecretAsync( secret, secret.Name(), secret.Namespace(), cancellationToken: cancellationToken)); }
//--------------------------------------------------------------------- // $note(jefflill): // // The prebuilder tool is not able to generate the Kubernetes client related extensions // defined in [Neon.Kube.KubernetesExtensions] due to a chicken-and-egg situation, so // we're just going to implement these here manually. /// <summary> /// Adds a new Kubernetes secret or updates an existing secret. /// </summary> /// <param name="secret">The secret.</param> /// <param name="namespace">Optionally overrides the default namespace.</param> /// <returns>The updated secret.</returns> public async Task <V1Secret> UpsertSecretAsync(V1Secret secret, string @namespace = null) { await SyncContext.Clear; return(await NormalizedRetryPolicy.InvokeAsync( async() => { return await k8s.UpsertSecretAsync(secret, @namespace); })); }
public void ReferenceComparisonTest() { var secret1 = new V1Secret(); var secret2 = secret1; Assert.True(Comparer.Equals(secret1, secret2)); Assert.False(Comparer.Equals(null, secret2)); Assert.False(Comparer.Equals(secret1, null)); }
private static string SerializeSecretToYaml(V1Secret secret) { var serializer = new SerializerBuilder() .WithNamingConvention(KubernetesNamingConvention.Instance) .ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull) .WithTypeConverter(DateTimeRfc3339Converter.Instance) .WithEventEmitter(nextEmitter => new QuoteSurroundingEventEmitter(nextEmitter)) .Build(); return(serializer.Serialize(secret)); }
public static V1Secret?AsSecret(this PairingRecord?pairingRecord) { if (pairingRecord == null) { return(null); } var secret = new V1Secret() { ApiVersion = V1Secret.KubeApiVersion, Kind = V1Secret.KubeKind, Type = TlsType, Metadata = new V1ObjectMeta(), Data = new Dictionary <string, byte[]>(), Immutable = true, }; secret.Data[TlsCertificateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "CERTIFICATE", pairingRecord.HostCertificate.Export(X509ContentType.Cert))); secret.Data[TlsPrivateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "PRIVATE KEY", pairingRecord.HostPrivateKey.ExportPkcs8PrivateKey())); secret.Data[CaCertificateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "CERTIFICATE", pairingRecord.RootCertificate.Export(X509ContentType.Cert))); secret.Data[CaPrivateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "PRIVATE KEY", pairingRecord.RootPrivateKey.ExportPkcs8PrivateKey())); secret.Data[DeviceCertificateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "CERTIFICATE", pairingRecord.DeviceCertificate.Export(X509ContentType.Cert))); secret.Data[EscrowBagKey] = pairingRecord.EscrowBag; secret.Data[HostIdKey] = Encoding.UTF8.GetBytes(pairingRecord.HostId); secret.Data[SystemBuidKey] = Encoding.UTF8.GetBytes(pairingRecord.SystemBUID); secret.Data[WifiMacAddressKey] = pairingRecord.WiFiMacAddress == null ? null : Encoding.UTF8.GetBytes(pairingRecord.WiFiMacAddress); return(secret); }
public async Task DeleteFileShareSecretAsync(V1Secret secret) { V1PersistentVolumeList currentPvs = await k8sClient.ListPersistentVolumeAsync(labelSelector : Constants.LabelSelector); var existingPvSet = new Set <V1PersistentVolume>(currentPvs.Items .Where(pv => pv.Spec?.AzureFile?.SecretName == secret.Metadata.Name) .ToDictionary(pv => pv.Metadata.Name)); var desiredPvSet = Set <V1PersistentVolume> .Empty; var diff = desiredPvSet.Diff(existingPvSet, PvComparer); await this.ManagePvs(diff); }
private static void EnsureProvisioningProfileSecret(V1Secret secret) { if (secret == null) { throw new ArgumentNullException(nameof(secret)); } if (secret.Type != SignedDataType || secret.Data == null || !secret.Data.ContainsKey(SignedDataContent)) { throw new InvalidDataException(); } }
private static void EnsureTlsSecret(V1Secret secret) { if (secret == null) { throw new ArgumentNullException(nameof(secret)); } if (secret.Type != TlsType || secret.Data == null || !secret.Data.ContainsKey(TlsCertificate) || !secret.Data.ContainsKey(TlsPrivateKey)) { throw new InvalidDataException($"The secret {secret?.Metadata?.Name} is not a valid TLS secret."); } }
private async Task HandleAdd(KamusSecret kamusSecret) { var @namespace = kamusSecret.Metadata.NamespaceProperty ?? "default"; var serviceAccount = kamusSecret.ServiceAccount; var id = $"{@namespace}:{serviceAccount}"; var decryptedItems = new Dictionary <string, string>(); mLogger.Debug("Starting decrypting KamusSecret items. KamusSecret {name} in namesapce {namespace}", kamusSecret.Metadata.Name, @namespace); foreach (var item in kamusSecret.Data) { try { var decrypted = await mKeyManagement.Decrypt(item.Value, id); decryptedItems.Add(item.Key, decrypted); } catch (Exception e) { Log.Error(e, "Failed to decrypt KamusSecret key {key}. KamusSecret {name} in namesapce {namespace}", item.Key, kamusSecret.Metadata.Name, @namespace); return; } } mLogger.Debug("KamusSecret items decrypted successfully. KamusSecret {name} in namesapce {namespace}", kamusSecret.Metadata.Name, @namespace); var secret = new V1Secret { Metadata = new V1ObjectMeta { Name = kamusSecret.Metadata.Name, NamespaceProperty = @namespace }, Type = kamusSecret.Type, StringData = decryptedItems }; await mKubernetes.CreateNamespacedSecretAsync(secret, @namespace); mAuditLogger.Information("Created a secret from KamusSecret {name} in namesapce {namespace successfully.", kamusSecret.Metadata.Name, @namespace); }
public async Task <V1Secret> GetPrometheusScrapeConfigSecretAsync(CancellationToken cancellationToken) { Init(); V1Secret result = null; try { result = await _client.ReadNamespacedSecretAsync(SecretName, SecretNamespace, cancellationToken : cancellationToken); } catch (Microsoft.Rest.HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.NotFound) { try { // Check for prometheus server config in the default namespace as a failover result = await _client.ReadNamespacedSecretAsync(SecretName, "default", cancellationToken : cancellationToken); } catch (Microsoft.Rest.HttpOperationException ex2) when(ex.Response.StatusCode == HttpStatusCode.NotFound) { _logger.LogWarning(ex2, "Unable to access scrape config secret"); } } catch (Microsoft.Rest.HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.Forbidden) { _logger.LogCritical(ex, @$ " ------ Additional Info ------ Headers: {ex.Response.Headers} ReasonPhrase: {ex.Response.ReasonPhrase} StatusCode: {ex.Response.StatusCode} Content: {ex.Response.Content} "); throw; } return(result); }
//TODO public V1Job GetEUConverterAppSettingsSecret(int id) { V1Secret secret = new V1Secret() { ApiVersion = "batch/v1", Kind = V1Job.KubeKind, Metadata = new V1ObjectMeta() { Name = "eu-appsettings-secret" }, }; return(null); }
private async Task Annotate(V1Secret secret, CertificateDefinition certificate) { var secretAnnotations = new Dictionary <string, string>(secret.Metadata.Annotations ?? new Dictionary <string, string>()); var original = secretAnnotations.ToDictionary(s => s.Key, s => s.Value); var certificateAnnotations = new Dictionary <string, string>(certificate.Metadata.Annotations ?? new Dictionary <string, string>()); if (certificateAnnotations.TryGetValue(Annotations.CertManagerCertificate.SecretReflectionAllowed, out var reflectionAllowed)) { secretAnnotations[Annotations.Reflection.Allowed] = reflectionAllowed; } else { secretAnnotations.Remove(Annotations.Reflection.Allowed); } if (certificateAnnotations.TryGetValue(Annotations.CertManagerCertificate.SecretReflectionAllowedNamespaces, out var allowedNamespaces)) { secretAnnotations[Annotations.Reflection.AllowedNamespaces] = allowedNamespaces; } else { secretAnnotations.Remove(Annotations.Reflection.AllowedNamespaces); } if (secretAnnotations.Count == original.Count && secretAnnotations.Keys.All(s => original.ContainsKey(s)) && secretAnnotations.All(s => original[s.Key] == s.Value)) { _logger.LogDebug("Secret {secretNs}/{secretName} matches certificate {certNs}/{certName} reflection annotations", secret.Metadata.NamespaceProperty, secret.Metadata.Name, certificate.Metadata.NamespaceProperty, certificate.Metadata.Name); return; } _logger.LogInformation( "Patching {secretNs}/{secretName} to match certificate {certNs}/{certName} reflection annotations", secret.Metadata.NamespaceProperty, secret.Metadata.Name, certificate.Metadata.NamespaceProperty, certificate.Metadata.Name); var patch = new JsonPatchDocument <V1Secret>(); patch.Replace(e => e.Metadata.Annotations, secretAnnotations); await _apiClient.PatchNamespacedSecretWithHttpMessagesAsync(new V1Patch(patch), secret.Metadata.Name, secret.Metadata.NamespaceProperty); }
async Task ManageImagePullSecrets(V1SecretList existing, List <V1Secret> desired, CancellationToken token) { // find difference between desired and existing image pull secrets var diff = FindImagePullSecretDiff(desired, existing.Items); // Update only those image pull secrets if configurations have not matched var updatingTask = diff.Updated .Select( update => { Events.UpdateImagePullSecret(update.To); update.To.Metadata.ResourceVersion = update.From.Metadata.ResourceVersion; return(this.client.ReplaceNamespacedSecretAsync(update.To, update.To.Metadata.Name, this.deviceNamespace, cancellationToken: token)); }); await Task.WhenAll(updatingTask); // Delete all existing image pull secrets that are not in desired list var removingTasks = diff.Removed .Select( name => { Events.DeleteImagePullSecret(name); return(this.client.DeleteNamespacedSecretAsync(name, this.deviceNamespace, cancellationToken: token)); }); await Task.WhenAll(removingTasks); // Create new desired image pull secrets foreach (V1Secret secret in diff.Added) { // Allow user to override image pull secrets even if they were created not by agent (e.g. during installation and/or iotedged) try { Events.CreateImagePullSecret(secret); await this.client.CreateNamespacedSecretAsync(secret, this.deviceNamespace, cancellationToken : token); } catch (HttpOperationException e) when(e.Response.StatusCode == HttpStatusCode.Conflict) { Events.UpdateExistingImagePullSecret(secret); V1Secret conflictedSecret = await this.client.ReadNamespacedSecretAsync(secret.Metadata.Name, secret.Metadata.NamespaceProperty, cancellationToken : token); conflictedSecret.Data = secret.Data; await this.client.ReplaceNamespacedSecretAsync(conflictedSecret, conflictedSecret.Metadata.Name, conflictedSecret.Metadata.NamespaceProperty, cancellationToken : token); } } }
private static void DecodeSecret(V1Secret secret) { secret.StringData ??= new Dictionary <string, string>(); if (secret.Data != null) { foreach (var kvp in secret.Data) { var key = kvp.Key; var value = kvp.Value; secret.StringData[key] = Encoding.UTF8.GetString(value); } } secret.Data = null; }
public async void Execute_UpdatesSecretData_WhenImagePullSecretCreatedNotByAgent() { string secretName = "username-docker.io"; var existingSecret = new V1Secret { Data = new Dictionary <string, byte[]> { [KubernetesConstants.K8sPullSecretData] = Encoding.UTF8.GetBytes("Invalid Secret Data") }, Type = KubernetesConstants.K8sPullSecretType, Metadata = new V1ObjectMeta { Name = secretName, NamespaceProperty = Namespace, ResourceVersion = "1" } }; IModule dockerModule = new DockerModule("module1", "v1", ModuleStatus.Running, Core.RestartPolicy.Always, Config1, ImagePullPolicy.OnCreate, Core.Constants.DefaultPriority, DefaultConfigurationInfo, EnvVars); var dockerConfigProvider = new Mock <ICombinedConfigProvider <CombinedDockerConfig> >(); dockerConfigProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime)) .Returns(() => new CombinedDockerConfig("test-image:1", Config1.CreateOptions, Option.None <string>(), Option.Maybe(DockerAuth))); var configProvider = new Mock <ICombinedConfigProvider <CombinedKubernetesConfig> >(); configProvider.Setup(cp => cp.GetCombinedConfig(dockerModule, Runtime)) .Returns(() => new CombinedKubernetesConfig("test-image:1", CreatePodParameters.Create(image: "test-image:1"), Option.Maybe(ImagePullSecret))); var client = new Mock <IKubernetes>(); client.SetupListSecrets().ReturnsAsync(() => CreateResponse(new V1SecretList { Items = new List <V1Secret>() })); client.SetupCreateSecret().ThrowsAsync(new HttpOperationException { Response = new HttpResponseMessageWrapper(new HttpResponseMessage(HttpStatusCode.Conflict), "Conflict") }); V1Secret updatedSecret = null; client.SetupUpdateSecret() .Callback( (V1Secret body, string name, string ns, string dryRun, string fieldManager, string pretty, Dictionary <string, List <string> > customHeaders, CancellationToken token) => { updatedSecret = body; }) .ReturnsAsync(() => CreateResponse(updatedSecret)); client.SetupGetSecret(secretName).ReturnsAsync(() => CreateResponse(existingSecret)); var cmd = new EdgeDeploymentCommand(ResourceName, Selector, Namespace, client.Object, new[] { dockerModule }, Option.None <EdgeDeploymentDefinition>(), Runtime, configProvider.Object, EdgeletModuleOwner); await cmd.ExecuteAsync(CancellationToken.None); Assert.True(Encoding.UTF8.GetBytes(ImagePullSecret.GenerateSecret()).SequenceEqual(updatedSecret.Data[KubernetesConstants.K8sPullSecretData])); Assert.Equal("1", updatedSecret.Metadata.ResourceVersion); client.VerifyAll(); }
async Task UpdateImagePullSecrets(IEnumerable <ImagePullSecret> imagePullSecrets, CancellationToken token) { foreach (var imagePullSecret in imagePullSecrets) { var secretMeta = new V1ObjectMeta( name: imagePullSecret.Name, namespaceProperty: this.deviceNamespace, ownerReferences: this.moduleOwner.ToOwnerReferences()); var secretData = new Dictionary <string, byte[]> { [Constants.K8sPullSecretData] = Encoding.UTF8.GetBytes(imagePullSecret.GenerateSecret()) }; var newSecret = new V1Secret("v1", secretData, type: Constants.K8sPullSecretType, kind: "Secret", metadata: secretMeta); Option <V1Secret> currentSecret; try { currentSecret = Option.Maybe(await this.client.ReadNamespacedSecretAsync(imagePullSecret.Name, this.deviceNamespace, cancellationToken: token)); } catch (Exception ex) when(!ex.IsFatal()) { Events.FailedToFindSecret(imagePullSecret.Name, ex); currentSecret = Option.None <V1Secret>(); } try { var v1Secret = await currentSecret.Match( async s => { if (s.Data != null && s.Data.TryGetValue(Constants.K8sPullSecretData, out byte[] pullSecretData) && pullSecretData.SequenceEqual(secretData[Constants.K8sPullSecretData])) { return(s); } return(await this.client.ReplaceNamespacedSecretAsync( newSecret, imagePullSecret.Name, this.deviceNamespace, cancellationToken: token)); }, async() => await this.client.CreateNamespacedSecretAsync(newSecret, this.deviceNamespace, cancellationToken: token)); if (v1Secret == null) { throw new InvalidIdentityException("Image pull secret was not properly created"); } }
public static async Task PushNotification( WatchEventType eventType, HealthCheckResource resource, V1Service uiService, V1Service notificationService, V1Secret endpointSecret, ILogger <K8sOperator> logger, IHttpClientFactory httpClientFactory) { var address = KubernetesAddressFactory.CreateHealthAddress(notificationService, resource); var uiAddress = KubernetesAddressFactory.CreateAddress(uiService, resource); dynamic healthCheck = new { Type = eventType, notificationService.Metadata.Name, Uri = address }; var client = httpClientFactory.CreateClient(); try { string type = healthCheck.Type.ToString(); string name = healthCheck.Name; string uri = healthCheck.Uri; logger.LogInformation("[PushService] Namespace {Namespace} - Sending Type: {type} - Service {name} with uri : {uri} to ui endpoint: {address}", resource.Metadata.NamespaceProperty, type, name, uri, uiAddress); var key = Encoding.UTF8.GetString(endpointSecret.Data["key"]); var response = await client.PostAsync($"{uiAddress}{Constants.PushServicePath}?{Constants.PushServiceAuthKey}={key}", new StringContent(JsonSerializer.Serialize(healthCheck, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }), Encoding.UTF8, "application/json")); logger.LogInformation("[PushService] Notification result for {name} - status code: {statuscode}", notificationService.Metadata.Name, response.StatusCode); } catch (Exception ex) { logger.LogError("Error notifying healthcheck service: {message}", ex.Message); } }
private static string SerializeSecret(V1Secret secret, OutputType outputType) { switch (outputType) { case OutputType.Json: return(SerializeSecretToJson(secret)); case OutputType.Yaml: return(SerializeSecretToYaml(secret)); default: throw new ArgumentOutOfRangeException( nameof(outputType), outputType, null); } }
public void AsX509Certificate2_Works() { // https://github.com/kubernetes-sigs/cluster-api/blob/master/docs/book/src/tasks/certs/using-custom-certificates.md V1Secret secret = new V1Secret() { Data = new Dictionary <string, byte[]>(), Type = "kubernetes.io/tls", }; secret.Data["tls.crt"] = File.ReadAllBytes("DeveloperProfiles/tls.crt"); secret.Data["tls.key"] = File.ReadAllBytes("DeveloperProfiles/tls.key"); var certificate = secret.AsX509Certificate2(); Assert.NotNull(certificate); Assert.Equal("CN=Test", certificate.Subject); Assert.True(certificate.HasPrivateKey); }
public void AsSignedCms_Works() { // https://github.com/kubernetes-sigs/cluster-api/blob/master/docs/book/src/tasks/certs/using-custom-certificates.md V1Secret secret = new V1Secret() { Data = new Dictionary <string, byte[]>(), Type = "kaponata.io/signedData", }; secret.Data["signedData"] = File.ReadAllBytes("DeveloperProfiles/test.mobileprovision"); var cms = secret.AsSignedCms(); var certificate = cms.Certificates[0]; Assert.NotNull(certificate); Assert.Equal("CN=Apple iPhone Certification Authority, OU=Apple Certification Authority, O=Apple Inc., C=US", certificate.Subject); Assert.False(certificate.HasPrivateKey); }
/// <summary> /// Converts this <see cref="SignedCms"/> to a <see cref="V1Secret"/>. /// </summary> /// <param name="signedData"> /// A <see cref="SignedCms"/> which represents a CMS signed data object. /// </param> /// <returns> /// The equivalent <see cref="V1Secret"/>. /// </returns> public static V1Secret AsSecret(this SignedCms signedData) { var secret = new V1Secret() { ApiVersion = V1Secret.KubeApiVersion, Kind = V1Secret.KubeKind, Type = SignedDataType, Metadata = new V1ObjectMeta() { Labels = new Dictionary <string, string>(), }, Data = new Dictionary <string, byte[]>(), Immutable = true, }; secret.Data[SignedDataContent] = signedData.Encode(); return(secret); }
private void ProcessData(V1Secret item) { if (item is null) { Logger?.LogWarning("ConfigMap response is null, no data could be processed"); return; } var secretContents = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); if (item?.Data != null) { foreach (var data in item.Data) { secretContents[NormalizeKey(data.Key)] = Encoding.UTF8.GetString(data.Value); } } Data = secretContents; }