diff --git a/.github/workflows/keyfactor-release-workflow.yml b/.github/workflows/keyfactor-release-workflow.yml new file mode 100644 index 0000000..e626ad7 --- /dev/null +++ b/.github/workflows/keyfactor-release-workflow.yml @@ -0,0 +1,19 @@ +name: Keyfactor Release Workflow + +on: + workflow_dispatch: + pull_request: + types: [opened, closed, synchronize, edited, reopened] + push: + create: + branches: + - 'release-*.*' + +jobs: + call-starter-workflow: + uses: keyfactor/actions/.github/workflows/starter.yml@v5 + secrets: + token: ${{ secrets.V2BUILDTOKEN}} # REQUIRED + gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }} # Only required for golang builds + gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} # Only required for golang builds + scan_token: ${{ secrets.SAST_TOKEN }} # REQUIRED diff --git a/.gitignore b/.gitignore index dfa446b..48f1278 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,9 @@ Thumbs.db ## Secrets — never commit credentials *.local.json secrets.json + +## Reference-only: Cloud Manager OpenAPI spec (kept locally, not committed) +api.yaml + +## License header template (tooling artifact, not committed) +.licenseheader diff --git a/AEMCM.Orchestrator.Tests/BudgetManagerTests.cs b/AEMCM.Orchestrator.Tests/BudgetManagerTests.cs index c981b96..3141ef3 100644 --- a/AEMCM.Orchestrator.Tests/BudgetManagerTests.cs +++ b/AEMCM.Orchestrator.Tests/BudgetManagerTests.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Collections.Generic; using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; using Keyfactor.Extensions.Orchestrator.AEMCM.Logic; diff --git a/AEMCM.Orchestrator.Tests/CertMatcherTests.cs b/AEMCM.Orchestrator.Tests/CertMatcherTests.cs index bc8a5c1..65d060d 100644 --- a/AEMCM.Orchestrator.Tests/CertMatcherTests.cs +++ b/AEMCM.Orchestrator.Tests/CertMatcherTests.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Collections.Generic; using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; using Keyfactor.Extensions.Orchestrator.AEMCM.Logic; @@ -76,6 +84,18 @@ public void Superset_MatchesOnlyWhenEnabled() Assert.Equal(3, enabled.Certificate!.Id); } + [Fact] + public void AliasMatches_Name_Id_AndDisambiguatedForm() + { + var cert = Cert(123, "wildcard-example", SslCertificateType.Ov, "a.example.com"); + + Assert.True(CertMatcher.AliasMatches(cert, "wildcard-example")); // by name + Assert.True(CertMatcher.AliasMatches(cert, "123")); // by id + Assert.True(CertMatcher.AliasMatches(cert, "wildcard-example (123)")); // disambiguated form + Assert.False(CertMatcher.AliasMatches(cert, "something-else")); + Assert.False(CertMatcher.AliasMatches(cert, "")); + } + [Fact] public void NoCandidates_ReturnsNoMatch() { diff --git a/AEMCM.Orchestrator.Tests/CloudManagerClientTests.cs b/AEMCM.Orchestrator.Tests/CloudManagerClientTests.cs new file mode 100644 index 0000000..3e0ecf2 --- /dev/null +++ b/AEMCM.Orchestrator.Tests/CloudManagerClientTests.cs @@ -0,0 +1,211 @@ +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Net; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using AEMCM.Orchestrator.Tests.TestHelpers; +using Keyfactor.Extensions.Orchestrator.AEMCM; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace AEMCM.Orchestrator.Tests +{ + /// + /// Exercises the real over the HTTP/serialization layer + /// (via a stubbed handler) — covering the write paths Adobe won't let us drive live. + /// + public class CloudManagerClientTests + { + private const long ProgramId = 211102; + + private sealed class StubAuth : IAdobeImsAuthClient + { + public Task GetAccessTokenAsync(CancellationToken cancellationToken = default) => + Task.FromResult("test-token"); + } + + private static CloudManagerClient BuildClient(StubHttpMessageHandler handler, IAdobeImsAuthClient? auth = null) => + new(new HttpClient(handler), auth ?? new StubAuth(), NullLogger.Instance, + "https://cloudmanager.adobe.io", ProgramId, apiKey: "api-key-123", imsOrgId: "org@AdobeOrg"); + + private static CreateOrUpdateSslCertificateBody SampleBody() => new() + { + Name = "my-cert", + Certificate = "-----BEGIN CERTIFICATE-----AAA-----END CERTIFICATE-----", + PrivateKey = new PrivateKeyValue { Value = "-----BEGIN PRIVATE KEY-----BBB-----END PRIVATE KEY-----" }, + Chain = "-----BEGIN CERTIFICATE-----CCC-----END CERTIFICATE-----", + }; + + private static string Serialize(object o) => JsonSerializer.Serialize(o, AemcmJson.Options); + + private static AllSslCertificatesList BuildList(int count, bool hasNext, int startId = 0) + { + var list = new AllSslCertificatesList { TotalNumberOfItems = count }; + for (var i = 0; i < count; i++) + { + list.Embedded.Certificates.Add(new SslCertificateRepresentation + { + Id = startId + i, + Name = $"c{startId + i}", + SslCertificateType = SslCertificateType.Ov, + SslCertificateStatus = SslCertificateStatus.Valid, + }); + } + if (hasNext) + list.Links.Next = new HalLink { Href = $"/api/program/{ProgramId}/certificates?start=100&limit=100" }; + return list; + } + + [Fact] + public void CreateCertificate_PostsExpectedBody_AndParsesResponse() + { + var handler = new StubHttpMessageHandler((_, _) => + StubHttpMessageHandler.Json(HttpStatusCode.Created, + "{\"id\":777,\"name\":\"my-cert\",\"sslCertificateType\":\"OV\"}")); + var client = BuildClient(handler); + + var result = client.CreateCertificateAsync(SampleBody()).GetAwaiter().GetResult(); + + Assert.Equal(777, result.Id); + var req = Assert.Single(handler.Requests); + Assert.Equal(HttpMethod.Post, req.Method); + Assert.EndsWith($"/api/program/{ProgramId}/certificates", req.Uri.AbsolutePath); + // Body field names must match the Cloud Manager contract (note the nested privateKey.value). + Assert.NotNull(req.Body); + Assert.Contains("\"name\":\"my-cert\"", req.Body!); + Assert.Contains("\"certificate\":", req.Body!); + Assert.Contains("\"privateKey\":{\"value\":", req.Body!); + Assert.Contains("\"chain\":", req.Body!); + // Auth + Adobe headers present. + Assert.Equal("Bearer", req.Message.Headers.Authorization!.Scheme); + Assert.Equal("test-token", req.Message.Headers.Authorization!.Parameter); + Assert.True(req.Message.Headers.Contains("x-api-key")); + Assert.True(req.Message.Headers.Contains("x-gw-ims-org-id")); + } + + [Fact] + public void UpdateCertificate_PutsToIdPath() + { + var handler = new StubHttpMessageHandler((_, _) => + StubHttpMessageHandler.Json(HttpStatusCode.OK, "{\"id\":55,\"name\":\"my-cert\"}")); + var client = BuildClient(handler); + + var result = client.UpdateCertificateAsync(55, SampleBody()).GetAwaiter().GetResult(); + + Assert.Equal(55, result.Id); + var req = Assert.Single(handler.Requests); + Assert.Equal(HttpMethod.Put, req.Method); + Assert.EndsWith($"/api/program/{ProgramId}/certificate/55", req.Uri.AbsolutePath); + } + + [Fact] + public void DeleteCertificate_SendsDeleteToIdPath() + { + var handler = new StubHttpMessageHandler((_, _) => StubHttpMessageHandler.Empty(HttpStatusCode.OK)); + var client = BuildClient(handler); + + client.DeleteCertificateAsync(55).GetAwaiter().GetResult(); + + var req = Assert.Single(handler.Requests); + Assert.Equal(HttpMethod.Delete, req.Method); + Assert.EndsWith($"/api/program/{ProgramId}/certificate/55", req.Uri.AbsolutePath); + } + + [Fact] + public void GetAllCertificates_PagesAcrossMultiplePages() + { + var handler = new StubHttpMessageHandler((req, _) => + req.RequestUri!.Query.Contains("start=0") + ? StubHttpMessageHandler.Json(HttpStatusCode.OK, Serialize(BuildList(100, hasNext: true))) + : StubHttpMessageHandler.Json(HttpStatusCode.OK, Serialize(BuildList(1, hasNext: false, startId: 1000)))); + var client = BuildClient(handler); + + var certs = client.GetAllCertificatesAsync().GetAwaiter().GetResult(); + + Assert.Equal(101, certs.Count); + Assert.Equal(2, handler.Requests.Count); + Assert.Contains(handler.Requests, r => r.Uri.Query.Contains("start=0")); + Assert.Contains(handler.Requests, r => r.Uri.Query.Contains("start=100")); + } + + [Fact] + public void GetDomainMappingsForCertificate_FiltersByIdAndParses() + { + const string json = + "{\"totalNumberOfItems\":1,\"domainMappings\":[{\"domainMappingId\":1,\"programId\":211102,\"certificateId\":55,\"domainName\":\"www.example.com\"}]}"; + var handler = new StubHttpMessageHandler((_, _) => StubHttpMessageHandler.Json(HttpStatusCode.OK, json)); + var client = BuildClient(handler); + + var mappings = client.GetDomainMappingsForCertificateAsync(55).GetAwaiter().GetResult(); + + var mapping = Assert.Single(mappings); + Assert.Equal("www.example.com", mapping.DomainName); + var req = Assert.Single(handler.Requests); + Assert.EndsWith($"/api/program/{ProgramId}/domain-mappings", req.Uri.AbsolutePath); + Assert.Contains("certificateId=55", req.Uri.Query); + } + + [Fact] + public void ErrorResponse_PolicyRejection_ThrowsFriendlyException() + { + const string errorBody = "{\"status\":400,\"title\":\"SSL Certificate validation error\"," + + "\"additionalProperties\":{\"errors\":[" + + "{\"field\":\"certificate\",\"code\":\"INVALID_CERTIFICATE_SIGNATURE\",\"message\":\"Signature of the certificate or chain is corrupt or invalid\"}," + + "{\"field\":\"certificate\",\"code\":\"INVALID_CERTIFICATE_POLICY\",\"message\":\"Certificate policy must be EV or OV, not DV.\"}]}}"; + var handler = new StubHttpMessageHandler((_, _) => + StubHttpMessageHandler.Json(HttpStatusCode.BadRequest, errorBody)); + var client = BuildClient(handler); + + var ex = Assert.Throws(() => + client.CreateCertificateAsync(SampleBody()).GetAwaiter().GetResult()); + + Assert.Equal(400, ex.StatusCode); + Assert.Contains("OV or EV", ex.Message); + Assert.DoesNotContain("Signature", ex.Message); + Assert.NotNull(ex.ResponseBody); + Assert.Contains("INVALID_CERTIFICATE_POLICY", ex.ResponseBody!); // raw body preserved for logs + } + + [Fact] + public void Unauthorized_RefreshesTokenAndRetriesOnce() + { + var tokenCalls = 0; + var cmCalls = 0; + var handler = new StubHttpMessageHandler((req, _) => + { + if (req.RequestUri!.AbsoluteUri.Contains("/ims/token")) + { + tokenCalls++; + return StubHttpMessageHandler.Json(HttpStatusCode.OK, + "{\"access_token\":\"tok\",\"token_type\":\"bearer\",\"expires_in\":3600}"); + } + + cmCalls++; + return cmCalls == 1 + ? StubHttpMessageHandler.Empty(HttpStatusCode.Unauthorized) + : StubHttpMessageHandler.Json(HttpStatusCode.OK, Serialize(BuildList(0, hasNext: false))); + }); + + var http = new HttpClient(handler); + var auth = new AdobeImsAuthClient(http, NullLogger.Instance, + "https://ims.example/ims/token/v3", "client-id", "client-secret", "openid"); + var client = new CloudManagerClient(http, auth, NullLogger.Instance, + "https://cloudmanager.adobe.io", ProgramId, "client-id", "org@AdobeOrg"); + + var certs = client.GetAllCertificatesAsync().GetAwaiter().GetResult(); + + Assert.Empty(certs); + Assert.Equal(2, cmCalls); // 401, then success on retry + Assert.Equal(2, tokenCalls); // initial token + refresh after 401 + } + } +} diff --git a/AEMCM.Orchestrator.Tests/CloudManagerErrorTests.cs b/AEMCM.Orchestrator.Tests/CloudManagerErrorTests.cs new file mode 100644 index 0000000..1894b88 --- /dev/null +++ b/AEMCM.Orchestrator.Tests/CloudManagerErrorTests.cs @@ -0,0 +1,72 @@ +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Net.Http; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client; +using Xunit; + +namespace AEMCM.Orchestrator.Tests +{ + public class CloudManagerErrorTests + { + [Fact] + public void FormatError_PolicyRejection_ReturnsSimpleOvEvMessage() + { + // The exact shape Cloud Manager returned during testing (policy + signature errors together). + const string payload = @"{ + ""type"": ""about:blank"", + ""status"": 400, + ""title"": ""SSL Certificate validation error"", + ""additionalProperties"": { + ""errors"": [ + { ""field"": ""certificate"", ""code"": ""INVALID_CERTIFICATE_SIGNATURE"", ""message"": ""Signature of the certificate or chain is corrupt or invalid"" }, + { ""field"": ""chain"", ""code"": ""INVALID_CERTIFICATE_SIGNATURE"", ""message"": ""Signature of the certificate or chain is corrupt or invalid"" }, + { ""field"": ""certificate"", ""code"": ""INVALID_CERTIFICATE_POLICY"", ""message"": ""Certificate policy must be EV or OV, not DV."" } + ] + } + }"; + + var message = CloudManagerClient.FormatError(HttpMethod.Post, "/api/program/1/certificates", 400, payload); + + Assert.Contains("OV or EV", message); + Assert.Contains("DV", message); + // Keep it simple — the raw signature noise and JSON should not leak into the job message. + Assert.DoesNotContain("Signature", message); + Assert.DoesNotContain("INVALID_CERTIFICATE", message); + Assert.DoesNotContain("{", message); + } + + [Fact] + public void FormatError_NonPolicyValidationErrors_SurfacesDistinctMessages() + { + const string payload = @"{ + ""status"": 400, + ""title"": ""SSL Certificate validation error"", + ""additionalProperties"": { + ""errors"": [ + { ""field"": ""privateKey"", ""code"": ""INVALID_PRIVATE_KEY"", ""message"": ""Private key does not match the certificate"" } + ] + } + }"; + + var message = CloudManagerClient.FormatError(HttpMethod.Post, "/api/program/1/certificates", 400, payload); + + Assert.Contains("Private key does not match the certificate", message); + Assert.Contains("SSL Certificate validation error", message); + } + + [Fact] + public void FormatError_UnrecognizedBody_FallsBackToRawSummary() + { + var message = CloudManagerClient.FormatError(HttpMethod.Get, "/api/program/1/certificates", 500, "Internal Server Error"); + + Assert.Contains("/api/program/1/certificates", message); + Assert.Contains("500", message); + Assert.Contains("Internal Server Error", message); + } + } +} diff --git a/AEMCM.Orchestrator.Tests/DiscoveryParseTests.cs b/AEMCM.Orchestrator.Tests/DiscoveryParseTests.cs index 3f07749..bac7e25 100644 --- a/AEMCM.Orchestrator.Tests/DiscoveryParseTests.cs +++ b/AEMCM.Orchestrator.Tests/DiscoveryParseTests.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using Keyfactor.Extensions.Orchestrator.AEMCM; using Xunit; @@ -28,5 +36,29 @@ public void ParseProgramIds_EmptyOrMissing_ReturnsEmpty() Assert.Empty(Discovery.ParseProgramIds("{}")); Assert.Empty(Discovery.ParseProgramIds(@"{ ""_embedded"": { ""programs"": [] } }")); } + + [Fact] + public void ParseTenantIds_ReadsEmbeddedTenantIds() + { + const string payload = @"{ + ""_embedded"": { + ""tenants"": [ + { ""id"": ""14"", ""imsTenantId"": ""acmeCorp"" }, + { ""id"": ""15"", ""imsTenantId"": ""globex"" } + ] + } + }"; + + var ids = Discovery.ParseTenantIds(payload); + + Assert.Equal(new[] { "14", "15" }, ids); + } + + [Fact] + public void ParseTenantIds_EmptyOrMissing_ReturnsEmpty() + { + Assert.Empty(Discovery.ParseTenantIds("{}")); + Assert.Empty(Discovery.ParseTenantIds(@"{ ""_embedded"": { ""tenants"": [] } }")); + } } } diff --git a/AEMCM.Orchestrator.Tests/ManagementTests.cs b/AEMCM.Orchestrator.Tests/ManagementTests.cs new file mode 100644 index 0000000..e6110cd --- /dev/null +++ b/AEMCM.Orchestrator.Tests/ManagementTests.cs @@ -0,0 +1,235 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using AEMCM.Orchestrator.Tests.TestHelpers; +using Keyfactor.Extensions.Orchestrator.AEMCM; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; +using Keyfactor.Orchestrators.Common.Enums; +using Xunit; + +namespace AEMCM.Orchestrator.Tests +{ + public class ManagementTests + { + private const long JobId = 42; + + private static (Management job, FakeCloudManagerClient fake) BuildJob() + { + var fake = new FakeCloudManagerClient(); + var job = new Management(resolver: null!) { Client = fake }; + return (job, fake); + } + + private static string Pfx(int keySize = 2048, params string[] sans) => + Convert.ToBase64String(CertTestFactory.CreateSelfSignedRsaPfx("cert.example.com", + sans.Length > 0 ? sans : new[] { "cert.example.com" }, keySize)); + + private static string EcPfx(int bits = 256) => + Convert.ToBase64String(CertTestFactory.CreateSelfSignedEcdsaPfx("ec.example.com", + new[] { "ec.example.com" }, bits)); + + private static SslCertificateRepresentation Cert( + long id, string name, string type = SslCertificateType.Ov, params string[] sans) => new() + { + Id = id, + Name = name, + SslCertificateType = type, + SslCertificateStatus = SslCertificateStatus.Valid, + SubjectAlternativeNames = sans.ToList(), + }; + + // ── Add ─────────────────────────────────────────────────────────────── + + [Fact] + public void Add_NewCert_CreatesWithSplitBody() + { + var (job, fake) = BuildJob(); + + var result = job.PerformAddition("my-cert", Pfx(), CertTestFactory.DefaultPassword, + overwrite: false, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Success, result.Result); + Assert.Single(fake.Created); + Assert.Empty(fake.Updated); + Assert.Equal("my-cert", fake.Created[0].Name); + Assert.Contains("BEGIN PRIVATE KEY", fake.Created[0].PrivateKey.Value); + Assert.Contains("BEGIN CERTIFICATE", fake.Created[0].Certificate); + } + + [Fact] + public void Add_Overwrite_MatchByAlias_UpdatesInPlace() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(5, "my-cert")); + + var result = job.PerformAddition("my-cert", Pfx(), CertTestFactory.DefaultPassword, + overwrite: true, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Success, result.Result); + Assert.Empty(fake.Created); + Assert.Single(fake.Updated); + Assert.Equal(5, fake.Updated[0].Id); + } + + [Fact] + public void Add_DuplicateName_NoOverwrite_Fails() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(5, "my-cert")); + + var result = job.PerformAddition("my-cert", Pfx(), CertTestFactory.DefaultPassword, + overwrite: false, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("already exists", result.FailureMessage); + Assert.Empty(fake.Created); + Assert.Empty(fake.Updated); + } + + [Fact] + public void Add_AtCertificateLimit_Fails() + { + var (job, fake) = BuildJob(); + for (var i = 0; i < BudgetManagerLimit; i++) + fake.Existing.Add(Cert(i + 1, $"cert-{i}")); + + var result = job.PerformAddition("brand-new", Pfx(2048, "brand-new.example.com"), + CertTestFactory.DefaultPassword, overwrite: false, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("limit", result.FailureMessage); + Assert.Empty(fake.Created); + } + + [Fact] + public void Add_AliasResolvesToDvCert_Fails() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(9, "dv-cert", SslCertificateType.Dv)); + + var result = job.PerformAddition("dv-cert", Pfx(), CertTestFactory.DefaultPassword, + overwrite: true, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("Adobe-managed", result.FailureMessage); + Assert.Empty(fake.Created); + Assert.Empty(fake.Updated); + } + + [Fact] + public void Add_Rsa4096_RejectedByPolicy() + { + var (job, fake) = BuildJob(); + + var result = job.PerformAddition("big-rsa", Pfx(4096), CertTestFactory.DefaultPassword, + overwrite: false, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("RSA key size", result.FailureMessage); + Assert.Empty(fake.Created); + } + + [Fact] + public void Add_Ecdsa_Succeeds() + { + var (job, fake) = BuildJob(); + + var result = job.PerformAddition("ec-cert", EcPfx(256), CertTestFactory.DefaultPassword, + overwrite: false, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Success, result.Result); + Assert.Single(fake.Created); + } + + [Fact] + public void Add_NoContents_Fails() + { + var (job, _) = BuildJob(); + + var result = job.PerformAddition("x", contents: "", CertTestFactory.DefaultPassword, + overwrite: false, JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("contents", result.FailureMessage); + } + + // ── Remove ───────────────────────────────────────────────────────────── + + [Fact] + public void Remove_ExistingUnusedCert_Deletes() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(5, "my-cert")); + + var result = job.PerformRemoval("my-cert", JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Success, result.Result); + Assert.Contains(5, fake.Deleted); + } + + [Fact] + public void Remove_CertInUseByDomainMapping_Blocked() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(5, "my-cert")); + fake.DomainMappings[5] = new List + { + new() { DomainMappingId = 1, CertificateId = 5, DomainName = "www.example.com" }, + }; + + var result = job.PerformRemoval("my-cert", JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("in use", result.FailureMessage); + Assert.Empty(fake.Deleted); + } + + [Fact] + public void Remove_NoMatch_TreatedAsAlreadyRemoved() + { + var (job, fake) = BuildJob(); + + var result = job.PerformRemoval("ghost", JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Success, result.Result); + Assert.Empty(fake.Deleted); + } + + [Fact] + public void Remove_AmbiguousAlias_Fails() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(1, "dup")); + fake.Existing.Add(Cert(2, "dup")); + + var result = job.PerformRemoval("dup", JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("multiple", result.FailureMessage); + Assert.Empty(fake.Deleted); + } + + [Fact] + public void Remove_DvCert_Refused() + { + var (job, fake) = BuildJob(); + fake.Existing.Add(Cert(9, "dv-cert", SslCertificateType.Dv)); + + var result = job.PerformRemoval("dv-cert", JobId); + + Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result); + Assert.Contains("Adobe-managed", result.FailureMessage); + Assert.Empty(fake.Deleted); + } + + private const int BudgetManagerLimit = 70; + } +} diff --git a/AEMCM.Orchestrator.Tests/PfxSplitterTests.cs b/AEMCM.Orchestrator.Tests/PfxSplitterTests.cs index b345a29..440c4a3 100644 --- a/AEMCM.Orchestrator.Tests/PfxSplitterTests.cs +++ b/AEMCM.Orchestrator.Tests/PfxSplitterTests.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Linq; using System.Text.RegularExpressions; using AEMCM.Orchestrator.Tests.TestHelpers; diff --git a/AEMCM.Orchestrator.Tests/TestHelpers/CertTestFactory.cs b/AEMCM.Orchestrator.Tests/TestHelpers/CertTestFactory.cs index b8a40b5..4252ff1 100644 --- a/AEMCM.Orchestrator.Tests/TestHelpers/CertTestFactory.cs +++ b/AEMCM.Orchestrator.Tests/TestHelpers/CertTestFactory.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; diff --git a/AEMCM.Orchestrator.Tests/TestHelpers/FakeCloudManagerClient.cs b/AEMCM.Orchestrator.Tests/TestHelpers/FakeCloudManagerClient.cs new file mode 100644 index 0000000..d36c8d3 --- /dev/null +++ b/AEMCM.Orchestrator.Tests/TestHelpers/FakeCloudManagerClient.cs @@ -0,0 +1,79 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; + +namespace AEMCM.Orchestrator.Tests.TestHelpers +{ + /// + /// In-memory for exercising the Management job flows. + /// Configure and ; inspect the recorded + /// , , and lists after a call. + /// + public sealed class FakeCloudManagerClient : ICloudManagerClient + { + public List Existing { get; } = new(); + public Dictionary> DomainMappings { get; } = new(); + + public List Created { get; } = new(); + public List<(long Id, CreateOrUpdateSslCertificateBody Body)> Updated { get; } = new(); + public List Deleted { get; } = new(); + + public long NextCreatedId { get; set; } = 1000; + + public Task> GetAllCertificatesAsync( + string? sslCertificateTypeFilter = null, string? statusFilter = null, + CancellationToken cancellationToken = default) => + Task.FromResult>(Existing.ToList()); + + public Task GetCertificateAsync( + long certificateId, CancellationToken cancellationToken = default) => + Task.FromResult(Existing.FirstOrDefault(c => c.Id == certificateId)); + + public Task CreateCertificateAsync( + CreateOrUpdateSslCertificateBody body, CancellationToken cancellationToken = default) + { + Created.Add(body); + var created = new SslCertificateRepresentation + { + Id = NextCreatedId++, + Name = body.Name, + SslCertificateType = SslCertificateType.Ov, + SslCertificateStatus = SslCertificateStatus.Valid, + }; + Existing.Add(created); + return Task.FromResult(created); + } + + public Task UpdateCertificateAsync( + long certificateId, CreateOrUpdateSslCertificateBody body, CancellationToken cancellationToken = default) + { + Updated.Add((certificateId, body)); + var existing = Existing.FirstOrDefault(c => c.Id == certificateId) + ?? new SslCertificateRepresentation { Id = certificateId, Name = body.Name }; + return Task.FromResult(existing); + } + + public Task DeleteCertificateAsync(long certificateId, CancellationToken cancellationToken = default) + { + Deleted.Add(certificateId); + Existing.RemoveAll(c => c.Id == certificateId); + return Task.CompletedTask; + } + + public Task> GetDomainMappingsForCertificateAsync( + long certificateId, CancellationToken cancellationToken = default) => + Task.FromResult>( + DomainMappings.TryGetValue(certificateId, out var mappings) ? mappings : new List()); + } +} diff --git a/AEMCM.Orchestrator.Tests/TestHelpers/StubHttpMessageHandler.cs b/AEMCM.Orchestrator.Tests/TestHelpers/StubHttpMessageHandler.cs new file mode 100644 index 0000000..4b046db --- /dev/null +++ b/AEMCM.Orchestrator.Tests/TestHelpers/StubHttpMessageHandler.cs @@ -0,0 +1,51 @@ +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AEMCM.Orchestrator.Tests.TestHelpers +{ + /// A captured outgoing request (method, URI, body, and headers) for assertions. + public sealed record RecordedRequest(HttpMethod Method, Uri Uri, string? Body, HttpRequestMessage Message); + + /// + /// Test double for that lets a test drive + /// / over the real HTTP/serialization + /// path without a network. The responder receives the request and its (already-read) body string. + /// + public sealed class StubHttpMessageHandler : HttpMessageHandler + { + private readonly Func _responder; + + public List Requests { get; } = new(); + + public StubHttpMessageHandler(Func responder) => + _responder = responder; + + protected override async Task SendAsync( + HttpRequestMessage request, CancellationToken cancellationToken) + { + var body = request.Content == null + ? null + : await request.Content.ReadAsStringAsync().ConfigureAwait(false); + + Requests.Add(new RecordedRequest(request.Method, request.RequestUri!, body, request)); + return _responder(request, body); + } + + public static HttpResponseMessage Json(HttpStatusCode status, string json) => + new(status) { Content = new StringContent(json, Encoding.UTF8, "application/json") }; + + public static HttpResponseMessage Empty(HttpStatusCode status) => new(status); + } +} diff --git a/AEMCM.Orchestrator.sln b/AEMCM.Orchestrator.sln index 3e1400a..767a7c3 100644 --- a/AEMCM.Orchestrator.sln +++ b/AEMCM.Orchestrator.sln @@ -1,11 +1,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 +# Visual Studio Version 18 +VisualStudioVersion = 18.8.12009.203 stable MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AEMCM.Orchestrator", "AEMCM.Orchestrator\AEMCM.Orchestrator.csproj", "{1640EE58-48C7-497D-8397-A4AF4BDFEE80}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AEMCM.Orchestrator.Tests", "AEMCM.Orchestrator.Tests\AEMCM.Orchestrator.Tests.csproj", "{09E23D05-C505-4672-AB42-9CE081270CA9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docsource", "docsource", "{80D8D9AA-52BC-4554-99B4-C27F363A830F}" + ProjectSection(SolutionItems) = preProject + docsource\aemcm.md = docsource\aemcm.md + docsource\content.md = docsource\content.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6BC603AE-0C5C-4AFE-B206-0EB9C32086D4}" + ProjectSection(SolutionItems) = preProject + CHANGELOG.md = CHANGELOG.md + integration-manifest.json = integration-manifest.json + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/AEMCM.Orchestrator/AEMCM.Orchestrator.csproj b/AEMCM.Orchestrator/AEMCM.Orchestrator.csproj index 5a0f538..81d6c7f 100644 --- a/AEMCM.Orchestrator/AEMCM.Orchestrator.csproj +++ b/AEMCM.Orchestrator/AEMCM.Orchestrator.csproj @@ -8,6 +8,7 @@ latest enable disable + true false Copyright © Keyfactor @@ -17,10 +18,27 @@ Versions match the current reference extensions; pin to your target UO/Command release. --> - + + - - + + + + + + + + + + + diff --git a/AEMCM.Orchestrator/AemcmProperties.cs b/AEMCM.Orchestrator/AemcmProperties.cs index 76e98aa..2ae8bed 100644 --- a/AEMCM.Orchestrator/AemcmProperties.cs +++ b/AEMCM.Orchestrator/AemcmProperties.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Text.Json.Serialization; namespace Keyfactor.Extensions.Orchestrator.AEMCM diff --git a/AEMCM.Orchestrator/Client/AdobeImsAuthClient.cs b/AEMCM.Orchestrator/Client/AdobeImsAuthClient.cs index 4242a7d..4aed46c 100644 --- a/AEMCM.Orchestrator/Client/AdobeImsAuthClient.cs +++ b/AEMCM.Orchestrator/Client/AdobeImsAuthClient.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Collections.Generic; using System.Net.Http; diff --git a/AEMCM.Orchestrator/Client/CloudManagerClient.cs b/AEMCM.Orchestrator/Client/CloudManagerClient.cs index 2bb897f..059a737 100644 --- a/AEMCM.Orchestrator/Client/CloudManagerClient.cs +++ b/AEMCM.Orchestrator/Client/CloudManagerClient.cs @@ -1,11 +1,21 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using Keyfactor.Extensions.Orchestrator.AEMCM; @@ -164,9 +174,12 @@ public async Task> GetDomainMappingsForCertificateA if (!response.IsSuccessStatusCode) { + var statusCode = (int)response.StatusCode; + // Log the full raw response for troubleshooting; surface a clean message to the job. + _logger.LogError("Cloud Manager {Method} {Path} failed ({Status}): {Body}", + method, path, statusCode, payload); throw new CloudManagerApiException( - (int)response.StatusCode, - $"{method} {path} failed ({(int)response.StatusCode}): {Truncate(payload)}"); + statusCode, FormatError(method, path, statusCode, payload), payload); } if (typeof(T) == typeof(object) || string.IsNullOrWhiteSpace(payload)) @@ -180,14 +193,83 @@ public async Task> GetDomainMappingsForCertificateA private static string Truncate(string s, int max = 500) => string.IsNullOrEmpty(s) || s.Length <= max ? s : s.Substring(0, max) + "…"; + + /// + /// Translates a Cloud Manager error response into a concise, operator-friendly message. + /// The OV/EV policy rejection is special-cased into a single clear sentence; other + /// validation errors are surfaced as their distinct messages. Falls back to a truncated + /// raw body when the payload isn't a recognized error shape. + /// + internal static string FormatError(HttpMethod method, string path, int statusCode, string payload) + { + CloudManagerErrorResponse? error = null; + try + { + if (!string.IsNullOrWhiteSpace(payload)) + error = JsonSerializer.Deserialize(payload, AemcmJson.Options); + } + catch (JsonException) + { + // Not a JSON error body — fall through to the raw fallback. + } + + var errors = error?.AdditionalProperties?.Errors; + if (errors != null && errors.Count > 0) + { + // The certificate-policy rejection is the common, actionable case — keep it simple. + if (errors.Any(e => string.Equals(e.Code, "INVALID_CERTIFICATE_POLICY", StringComparison.OrdinalIgnoreCase))) + { + return "The certificate is not supported: AEM Cloud Manager requires an OV or EV certificate. " + + "DV and self-signed certificates are rejected."; + } + + var messages = errors + .Select(e => e.Message) + .Where(m => !string.IsNullOrWhiteSpace(m)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + if (messages.Count > 0) + { + var title = string.IsNullOrWhiteSpace(error!.Title) ? "Cloud Manager rejected the request" : error.Title!; + return $"{title}: {string.Join("; ", messages)}."; + } + } + + return $"{method} {path} failed ({statusCode}): {Truncate(payload)}"; + } } - /// Carries the HTTP status code so callers can special-case (e.g. 404, 429). + /// Cloud Manager RFC-7807-style error response with a nested validation-errors list. + internal sealed class CloudManagerErrorResponse + { + [JsonPropertyName("title")] public string? Title { get; set; } + [JsonPropertyName("status")] public int Status { get; set; } + [JsonPropertyName("additionalProperties")] public CloudManagerErrorDetails? AdditionalProperties { get; set; } + } + + internal sealed class CloudManagerErrorDetails + { + [JsonPropertyName("errors")] public List Errors { get; set; } = new(); + } + + internal sealed class CloudManagerFieldError + { + [JsonPropertyName("field")] public string? Field { get; set; } + [JsonPropertyName("code")] public string? Code { get; set; } + [JsonPropertyName("message")] public string? Message { get; set; } + } + + /// Carries the HTTP status code and raw response body so callers can special-case or log. public class CloudManagerApiException : Exception { public int StatusCode { get; } + public string? ResponseBody { get; } - public CloudManagerApiException(int statusCode, string message) : base(message) => + public CloudManagerApiException(int statusCode, string message, string? responseBody = null) : base(message) + { StatusCode = statusCode; + ResponseBody = responseBody; + } } } diff --git a/AEMCM.Orchestrator/Client/IAdobeImsAuthClient.cs b/AEMCM.Orchestrator/Client/IAdobeImsAuthClient.cs index f2260d7..d04d8fa 100644 --- a/AEMCM.Orchestrator/Client/IAdobeImsAuthClient.cs +++ b/AEMCM.Orchestrator/Client/IAdobeImsAuthClient.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Threading; using System.Threading.Tasks; diff --git a/AEMCM.Orchestrator/Client/ICloudManagerClient.cs b/AEMCM.Orchestrator/Client/ICloudManagerClient.cs index b7c7041..29555ef 100644 --- a/AEMCM.Orchestrator/Client/ICloudManagerClient.cs +++ b/AEMCM.Orchestrator/Client/ICloudManagerClient.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/AEMCM.Orchestrator/Client/Models/ApiModels.cs b/AEMCM.Orchestrator/Client/Models/ApiModels.cs index 5971566..1b52bb6 100644 --- a/AEMCM.Orchestrator/Client/Models/ApiModels.cs +++ b/AEMCM.Orchestrator/Client/Models/ApiModels.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/AEMCM.Orchestrator/Constants.cs b/AEMCM.Orchestrator/Constants.cs index a1744ec..c077eb3 100644 --- a/AEMCM.Orchestrator/Constants.cs +++ b/AEMCM.Orchestrator/Constants.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Text.Json; using System.Text.Json.Serialization; diff --git a/AEMCM.Orchestrator/JobAttribute.cs b/AEMCM.Orchestrator/JobAttribute.cs index 2ad1823..12a4f6b 100644 --- a/AEMCM.Orchestrator/JobAttribute.cs +++ b/AEMCM.Orchestrator/JobAttribute.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; namespace Keyfactor.Extensions.Orchestrator.AEMCM diff --git a/AEMCM.Orchestrator/Jobs/AemcmJob.cs b/AEMCM.Orchestrator/Jobs/AemcmJob.cs index 2a021c0..744332f 100644 --- a/AEMCM.Orchestrator/Jobs/AemcmJob.cs +++ b/AEMCM.Orchestrator/Jobs/AemcmJob.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Net.Http; using System.Text.Json; diff --git a/AEMCM.Orchestrator/Jobs/Discovery.cs b/AEMCM.Orchestrator/Jobs/Discovery.cs index 371bf25..20edaeb 100644 --- a/AEMCM.Orchestrator/Jobs/Discovery.cs +++ b/AEMCM.Orchestrator/Jobs/Discovery.cs @@ -1,9 +1,18 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; +using Keyfactor.Extensions.Orchestrator.AEMCM.Client; using Keyfactor.Logging; using Keyfactor.Orchestrators.Common.Enums; using Keyfactor.Orchestrators.Extensions; @@ -17,8 +26,11 @@ namespace Keyfactor.Extensions.Orchestrator.AEMCM /// programId as a discoverable store path. /// /// - /// TODO (DESIGN.md §8): confirm the exact tenant-scoped programs listing operation and the - /// required IMS scopes. This uses GET /api/programs and reads _embedded.programs[].id. + /// A Discovery job has no store, so it cannot read the store's custom fields. Supply one or + /// more comma-separated IMS Org IDs in the discovery Directories to search field. + /// For each org, this lists tenants (GET /api/tenants) and then that tenant's programs + /// (GET /api/tenant/{tenantId}/programs), aggregating the program IDs. The deprecated + /// GET /api/programs is intentionally not used. /// [Job(JobTypes.Discovery)] public class Discovery : AemcmJob, IDiscoveryJobExtension @@ -37,26 +49,34 @@ public JobResult ProcessJob(DiscoveryJobConfiguration config, SubmitDiscoveryUpd { InitializeStore(config); - var token = Auth!.GetAccessTokenAsync().GetAwaiter().GetResult(); - - using var request = new HttpRequestMessage( - HttpMethod.Get, $"{Properties.BaseUrl.TrimEnd('/')}/api/programs"); - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); - request.Headers.TryAddWithoutValidation("x-api-key", Properties.ClientId); - if (!string.IsNullOrEmpty(Properties.ImsOrgId)) - request.Headers.TryAddWithoutValidation("x-gw-ims-org-id", Properties.ImsOrgId); - request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + var orgIds = GetOrgIds(config); + if (orgIds.Count == 0) + { + return Fail(config, + "No IMS Org ID provided. Enter one or more comma-separated IMS Org IDs in the " + + "'Directories to search' field of the discovery schedule."); + } - using var response = Http.SendAsync(request).GetAwaiter().GetResult(); - var payload = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - if (!response.IsSuccessStatusCode) - return Fail(config, $"Programs listing failed ({(int)response.StatusCode}): {payload}"); + var token = Auth!.GetAccessTokenAsync().GetAwaiter().GetResult(); + var baseUrl = Properties.BaseUrl.TrimEnd('/'); + var programIds = new HashSet(StringComparer.Ordinal); - var programIds = ParseProgramIds(payload); + foreach (var orgId in orgIds) + { + var tenantsPayload = SendGet($"{baseUrl}/api/tenants", token, orgId); + foreach (var tenantId in ParseTenantIds(tenantsPayload)) + { + var programsPayload = SendGet( + $"{baseUrl}/api/tenant/{Uri.EscapeDataString(tenantId)}/programs", token, orgId); + foreach (var programId in ParseProgramIds(programsPayload)) + programIds.Add(programId); + } + } - var accepted = submitDiscovery.Invoke(programIds); + var discovered = programIds.ToList(); + var accepted = submitDiscovery.Invoke(discovered); Logger.LogInformation("AEMCM Discovery found {Count} program(s); accepted={Accepted}", - programIds.Count, accepted); + discovered.Count, accepted); return new JobResult { @@ -72,18 +92,50 @@ public JobResult ProcessJob(DiscoveryJobConfiguration config, SubmitDiscoveryUpd } } - public static List ParseProgramIds(string payload) + private string SendGet(string url, string token, string orgId) + { + using var request = new HttpRequestMessage(HttpMethod.Get, url); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + request.Headers.TryAddWithoutValidation("x-api-key", Properties.ClientId); + request.Headers.TryAddWithoutValidation("x-gw-ims-org-id", orgId); + request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + using var response = Http.SendAsync(request).GetAwaiter().GetResult(); + var payload = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + if (!response.IsSuccessStatusCode) + throw new CloudManagerApiException((int)response.StatusCode, $"GET {url} failed ({(int)response.StatusCode}): {payload}"); + return payload; + } + + private static List GetOrgIds(DiscoveryJobConfiguration config) + { + var result = new List(); + if (config.JobProperties != null + && config.JobProperties.TryGetValue("dirs", out var value) + && value?.ToString() is { } raw + && !string.IsNullOrWhiteSpace(raw)) + { + result.AddRange(raw.Split(',').Select(s => s.Trim()).Where(s => s.Length > 0)); + } + return result; + } + + public static List ParseProgramIds(string payload) => ParseEmbeddedIds(payload, "programs"); + + public static List ParseTenantIds(string payload) => ParseEmbeddedIds(payload, "tenants"); + + private static List ParseEmbeddedIds(string payload, string collectionName) { var ids = new List(); using var doc = JsonDocument.Parse(payload); if (doc.RootElement.TryGetProperty("_embedded", out var embedded) - && embedded.TryGetProperty("programs", out var programs) - && programs.ValueKind == JsonValueKind.Array) + && embedded.TryGetProperty(collectionName, out var items) + && items.ValueKind == JsonValueKind.Array) { - foreach (var program in programs.EnumerateArray()) + foreach (var item in items.EnumerateArray()) { - if (!program.TryGetProperty("id", out var idElement)) continue; + if (!item.TryGetProperty("id", out var idElement)) continue; var id = idElement.ValueKind == JsonValueKind.String ? idElement.GetString() : idElement.GetRawText(); diff --git a/AEMCM.Orchestrator/Jobs/Inventory.cs b/AEMCM.Orchestrator/Jobs/Inventory.cs index 8ef116f..3dad915 100644 --- a/AEMCM.Orchestrator/Jobs/Inventory.cs +++ b/AEMCM.Orchestrator/Jobs/Inventory.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Collections.Generic; using System.Globalization; @@ -31,7 +39,21 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd // Report every cert (incl. Adobe-managed DV and expired) so the 70-cert budget is visible. var certs = Client!.GetAllCertificatesAsync().GetAwaiter().GetResult(); - var items = certs.Select(ToInventoryItem).ToList(); + + // Alias = Adobe certificate name. KF-managed names are kept unique on Add, but a + // program may already contain externally-created duplicates; disambiguate those with + // the id so Command never receives colliding aliases. + var duplicateNames = certs + .Where(c => !string.IsNullOrWhiteSpace(c.Name)) + .GroupBy(c => c.Name!, StringComparer.OrdinalIgnoreCase) + .Where(g => g.Count() > 1) + .Select(g => g.Key) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + + if (duplicateNames.Count > 0) + Logger.LogWarning("Found {Count} duplicate certificate name(s); those aliases are disambiguated with the certificate id.", duplicateNames.Count); + + var items = certs.Select(c => ToInventoryItem(c, duplicateNames)).ToList(); var accepted = submitInventoryUpdate.Invoke(items); Logger.LogInformation("AEMCM Inventory submitted {Count} item(s); accepted={Accepted}", items.Count, accepted); @@ -55,7 +77,8 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd } } - private static CurrentInventoryItem ToInventoryItem(SslCertificateRepresentation cert) + private static CurrentInventoryItem ToInventoryItem( + SslCertificateRepresentation cert, HashSet duplicateNames) { var pems = new List(); if (!string.IsNullOrWhiteSpace(cert.Certificate)) pems.Add(cert.Certificate!); @@ -64,9 +87,9 @@ private static CurrentInventoryItem ToInventoryItem(SslCertificateRepresentation return new CurrentInventoryItem { - Alias = string.IsNullOrWhiteSpace(cert.Name) - ? cert.Id.ToString(CultureInfo.InvariantCulture) - : cert.Name!, + // Alias = Adobe certificate name (round-trips with enrollment). Fall back to the id + // when the name is empty, and disambiguate pre-existing duplicate names with the id. + Alias = ResolveAlias(cert, duplicateNames), Certificates = pems, PrivateKeyEntry = true, // Adobe holds the key; it is never returned to us. UseChainLevel = hasChain, @@ -74,6 +97,7 @@ private static CurrentInventoryItem ToInventoryItem(SslCertificateRepresentation Parameters = new Dictionary { ["CertificateId"] = cert.Id, + ["Name"] = cert.Name ?? string.Empty, ["Type"] = cert.SslCertificateType ?? string.Empty, ["Status"] = cert.SslCertificateStatus ?? string.Empty, ["CommonName"] = cert.CommonName ?? string.Empty, @@ -83,5 +107,15 @@ private static CurrentInventoryItem ToInventoryItem(SslCertificateRepresentation }, }; } + + private static string ResolveAlias(SslCertificateRepresentation cert, HashSet duplicateNames) + { + if (string.IsNullOrWhiteSpace(cert.Name)) + return cert.Id.ToString(CultureInfo.InvariantCulture); + + return duplicateNames.Contains(cert.Name!) + ? $"{cert.Name} ({cert.Id.ToString(CultureInfo.InvariantCulture)})" + : cert.Name!; + } } } diff --git a/AEMCM.Orchestrator/Jobs/Management.cs b/AEMCM.Orchestrator/Jobs/Management.cs index 7bf28eb..255eb9b 100644 --- a/AEMCM.Orchestrator/Jobs/Management.cs +++ b/AEMCM.Orchestrator/Jobs/Management.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Globalization; using System.Linq; @@ -38,83 +46,111 @@ public JobResult ProcessJob(ManagementJobConfiguration config) { InitializeStore(config); + var jobCert = config.JobCertificate; return config.OperationType switch { - CertStoreOperationType.Add => HandleAdd(config), - CertStoreOperationType.Remove => HandleRemove(config), - _ => Fail(config, $"Unsupported operation '{config.OperationType}'."), + CertStoreOperationType.Add => PerformAddition( + jobCert?.Alias, jobCert?.Contents, jobCert?.PrivateKeyPassword, + config.Overwrite, config.JobHistoryId), + CertStoreOperationType.Remove => PerformRemoval(jobCert?.Alias, config.JobHistoryId), + _ => Fail(config.JobHistoryId, $"Unsupported operation '{config.OperationType}'."), }; } + catch (CloudManagerApiException apiEx) + { + // Message is already an operator-friendly summary of the Cloud Manager error. + Logger.LogError(apiEx, "AEMCM Management: Cloud Manager API error"); + return Fail(config.JobHistoryId, apiEx.Message); + } catch (Exception ex) { Logger.LogError(ex, "AEMCM Management failed"); - return Fail(config, $"AEMCM Management failed: {ex.Message}"); + return Fail(config.JobHistoryId, $"AEMCM Management failed: {ex.Message}"); } } - private JobResult HandleAdd(ManagementJobConfiguration config) + /// + /// Add/renew a certificate: split the PFX, validate platform rules, then update an existing + /// certificate (matched by alias or SAN set) or create a new one within the 70-cert budget. + /// + internal JobResult PerformAddition( + string? alias, string? contents, string? pfxPassword, bool overwrite, long jobHistoryId) { - var jobCert = config.JobCertificate; - if (string.IsNullOrWhiteSpace(jobCert?.Contents)) - return Fail(config, "No certificate contents supplied for Add."); + if (string.IsNullOrWhiteSpace(contents)) + return Fail(jobHistoryId, "No certificate contents supplied for Add."); // 1. Split the PFX into leaf / PKCS#8 key / chain-without-leaf. - var pfxBytes = Convert.FromBase64String(jobCert!.Contents); SplitCertificate split; try { - split = PfxSplitter.Split(pfxBytes, jobCert.PrivateKeyPassword); + split = PfxSplitter.Split(Convert.FromBase64String(contents!), pfxPassword); } catch (Exception ex) { - return Fail(config, $"Could not process the supplied certificate: {ex.Message}"); + return Fail(jobHistoryId, $"Could not process the supplied certificate: {ex.Message}"); } // 2. Validate against platform rules early. var validationError = ValidatePlatformRules(split); - if (validationError != null) return Fail(config, validationError); + if (validationError != null) return Fail(jobHistoryId, validationError); var body = new CreateOrUpdateSslCertificateBody { - Name = string.IsNullOrWhiteSpace(jobCert.Alias) ? split.CommonName : jobCert.Alias!, + Name = string.IsNullOrWhiteSpace(alias) ? split.CommonName : alias!, Certificate = split.CertificatePem, PrivateKey = new PrivateKeyValue { Value = split.PrivateKeyPkcs8Pem }, Chain = split.ChainPem, // leaf already excluded by PfxSplitter }; + // Pre-send diagnostic summary. Never logs private key material — only shape/metadata, + // so the first upload against a real cert is easy to diagnose (e.g. an empty chain). + Logger.LogDebug( + "Prepared certificate for upload: name={Name}, CN={CommonName}, SANs={SanCount}, key={KeyAlgorithm}-{KeySize}, chainCerts={ChainCount}.", + body.Name, split.CommonName, split.SubjectAlternativeNames.Count, + split.KeyAlgorithm, split.KeySize, CountChainCerts(split.ChainPem)); + // 3. Decide update vs add. var existing = Client!.GetAllCertificatesAsync().GetAwaiter().GetResult(); // Guard: alias explicitly targeting an Adobe-managed (DV) cert. - if (config.Overwrite && !string.IsNullOrWhiteSpace(jobCert.Alias)) + if (overwrite && !string.IsNullOrWhiteSpace(alias)) { - var aliasHit = existing.FirstOrDefault(c => AliasMatches(c, jobCert.Alias!)); + var aliasHit = existing.FirstOrDefault(c => CertMatcher.AliasMatches(c, alias!)); if (aliasHit is { IsAdobeManaged: true }) - return Fail(config, $"Alias '{jobCert.Alias}' resolves to an Adobe-managed (DV) certificate, which cannot be modified."); + return Fail(jobHistoryId, $"Alias '{alias}' resolves to an Adobe-managed (DV) certificate, which cannot be modified."); + } + + // Enforce name uniqueness (alias = Adobe cert name). Without Overwrite, a duplicate name + // is rejected so the alias stays a stable, round-tripping key. + if (!overwrite + && existing.Any(c => string.Equals(c.Name, body.Name, StringComparison.OrdinalIgnoreCase))) + { + return Fail(jobHistoryId, + $"A certificate named '{body.Name}' already exists in this program. Enable Overwrite to update it."); } var match = CertMatcher.FindMatch( - existing, split.SubjectAlternativeNames, jobCert.Alias, config.Overwrite, AllowSupersetConsolidation); + existing, split.SubjectAlternativeNames, alias, overwrite, AllowSupersetConsolidation); if (match.IsMatch) { - if (!config.Overwrite && match.MatchType != CertMatchType.Alias) + if (!overwrite && match.MatchType != CertMatchType.Alias) { - return Fail(config, + return Fail(jobHistoryId, $"An equivalent certificate (id {match.Certificate!.Id}) already exists. Enable Overwrite to update it."); } Logger.LogInformation("Updating existing certificate id {Id} (match={Match})", match.Certificate!.Id, match.MatchType); var updated = Client.UpdateCertificateAsync(match.Certificate.Id, body).GetAwaiter().GetResult(); - return Success(config, $"Updated certificate id {updated.Id}."); + return Success(jobHistoryId, $"Updated certificate id {updated.Id}."); } // 4. No match → create, budget permitting. if (BudgetManager.HasBudgetForNew(existing.Count)) { var created = Client.CreateCertificateAsync(body).GetAwaiter().GetResult(); - return Success(config, $"Created certificate id {created.Id}."); + return Success(jobHistoryId, $"Created certificate id {created.Id}."); } // 5. Budget exhausted → optional reclaim, else fail. @@ -126,45 +162,59 @@ private JobResult HandleAdd(ManagementJobConfiguration config) Logger.LogWarning("Budget full; reclaiming expired certificate id {Id}", reclaim.Id); Client.DeleteCertificateAsync(reclaim.Id).GetAwaiter().GetResult(); var created = Client.CreateCertificateAsync(body).GetAwaiter().GetResult(); - return Success(config, $"Reclaimed expired id {reclaim.Id}; created certificate id {created.Id}."); + return Success(jobHistoryId, $"Reclaimed expired id {reclaim.Id}; created certificate id {created.Id}."); } } - return Fail(config, + return Fail(jobHistoryId, $"Cannot add certificate: program is at the {BudgetManager.MaxCertificates}-certificate limit. " + "Delete expired or unused certificates and retry."); } - private JobResult HandleRemove(ManagementJobConfiguration config) + /// Remove a certificate by alias, blocking deletion when it is in use by a domain mapping. + internal JobResult PerformRemoval(string? alias, long jobHistoryId) { - var alias = config.JobCertificate?.Alias; if (string.IsNullOrWhiteSpace(alias)) - return Fail(config, "No alias supplied for Remove."); + return Fail(jobHistoryId, "No alias supplied for Remove."); var existing = Client!.GetAllCertificatesAsync().GetAwaiter().GetResult(); - var target = existing.FirstOrDefault(c => AliasMatches(c, alias!)); - if (target == null) + var matches = existing.Where(c => CertMatcher.AliasMatches(c, alias!)).ToList(); + if (matches.Count == 0) { Logger.LogInformation("Remove: no certificate matched alias '{Alias}'; treating as already removed.", alias); - return Success(config, $"No certificate matched alias '{alias}'."); + return Success(jobHistoryId, $"No certificate matched alias '{alias}'."); + } + + if (matches.Count > 1) + { + var ids = string.Join(", ", matches.Select(m => m.Id.ToString(CultureInfo.InvariantCulture))); + return Fail(jobHistoryId, + $"Alias '{alias}' matches multiple certificates (ids: {ids}). Remove by the disambiguated alias or resolve the duplicate names first."); } + var target = matches[0]; + if (target.IsAdobeManaged) - return Fail(config, $"Certificate '{alias}' is Adobe-managed (DV) and cannot be removed by this extension."); + return Fail(jobHistoryId, $"Certificate '{alias}' is Adobe-managed (DV) and cannot be removed by this extension."); // Safe-delete: block if any domain mapping references the cert. var mappings = Client.GetDomainMappingsForCertificateAsync(target.Id).GetAwaiter().GetResult(); if (mappings.Count > 0) { var names = string.Join(", ", mappings.Select(m => m.DomainName ?? m.DomainMappingId.ToString(CultureInfo.InvariantCulture))); - return Fail(config, + return Fail(jobHistoryId, $"Certificate id {target.Id} is in use by domain mapping(s): {names}. Remove the mapping(s) before deleting."); } Client.DeleteCertificateAsync(target.Id).GetAwaiter().GetResult(); - return Success(config, $"Deleted certificate id {target.Id}. Run the pipeline to fully undeploy."); + return Success(jobHistoryId, $"Deleted certificate id {target.Id}. Run the pipeline to fully undeploy."); } + private static int CountChainCerts(string? chainPem) => + string.IsNullOrEmpty(chainPem) + ? 0 + : chainPem.Split("-----BEGIN CERTIFICATE-----").Length - 1; + private static string? ValidatePlatformRules(SplitCertificate split) { if (!BudgetManager.IsWithinSanLimit(split.SubjectAlternativeNames.Count)) @@ -187,27 +237,23 @@ private JobResult HandleRemove(ManagementJobConfiguration config) return $"Unsupported key algorithm '{split.KeyAlgorithm}'."; } - private static bool AliasMatches(SslCertificateRepresentation cert, string alias) => - string.Equals(cert.Name, alias, StringComparison.OrdinalIgnoreCase) - || string.Equals(cert.Id.ToString(CultureInfo.InvariantCulture), alias, StringComparison.Ordinal); - - private JobResult Success(ManagementJobConfiguration config, string message) + private JobResult Success(long jobHistoryId, string message) { Logger.LogInformation("{Message}", message); return new JobResult { - JobHistoryId = config.JobHistoryId, + JobHistoryId = jobHistoryId, Result = OrchestratorJobStatusJobResult.Success, FailureMessage = string.Empty, }; } - private JobResult Fail(ManagementJobConfiguration config, string message) + private JobResult Fail(long jobHistoryId, string message) { Logger.LogError("{Message}", message); return new JobResult { - JobHistoryId = config.JobHistoryId, + JobHistoryId = jobHistoryId, Result = OrchestratorJobStatusJobResult.Failure, FailureMessage = message, }; diff --git a/AEMCM.Orchestrator/Logic/BudgetManager.cs b/AEMCM.Orchestrator/Logic/BudgetManager.cs index 7aaea6f..928e540 100644 --- a/AEMCM.Orchestrator/Logic/BudgetManager.cs +++ b/AEMCM.Orchestrator/Logic/BudgetManager.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System.Collections.Generic; using System.Linq; using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; diff --git a/AEMCM.Orchestrator/Logic/CertMatcher.cs b/AEMCM.Orchestrator/Logic/CertMatcher.cs index 89de7a2..5a2e12f 100644 --- a/AEMCM.Orchestrator/Logic/CertMatcher.cs +++ b/AEMCM.Orchestrator/Logic/CertMatcher.cs @@ -1,5 +1,14 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Keyfactor.Extensions.Orchestrator.AEMCM.Client.Models; @@ -82,9 +91,21 @@ public static CertMatchResult FindMatch( return CertMatchResult.NoMatch; } - private static bool AliasMatches(SslCertificateRepresentation cert, string alias) => - string.Equals(cert.Name, alias, StringComparison.OrdinalIgnoreCase) - || string.Equals(cert.Id.ToString(System.Globalization.CultureInfo.InvariantCulture), alias, StringComparison.Ordinal); + /// + /// Matches a Keyfactor alias to a certificate by name, by numeric id, or by the + /// disambiguated inventory form "name (id)" used for pre-existing duplicate names. + /// + public static bool AliasMatches(SslCertificateRepresentation cert, string alias) + { + if (string.IsNullOrWhiteSpace(alias)) return false; + + var id = cert.Id.ToString(CultureInfo.InvariantCulture); + if (string.Equals(id, alias, StringComparison.Ordinal)) return true; + if (string.Equals(cert.Name, alias, StringComparison.OrdinalIgnoreCase)) return true; + + return !string.IsNullOrWhiteSpace(cert.Name) + && string.Equals($"{cert.Name} ({id})", alias, StringComparison.OrdinalIgnoreCase); + } private static HashSet Normalize(IEnumerable sans) => new(sans.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim().ToLowerInvariant()), diff --git a/AEMCM.Orchestrator/Logic/PfxSplitter.cs b/AEMCM.Orchestrator/Logic/PfxSplitter.cs index 8d5d6a2..8b440d3 100644 --- a/AEMCM.Orchestrator/Logic/PfxSplitter.cs +++ b/AEMCM.Orchestrator/Logic/PfxSplitter.cs @@ -1,9 +1,21 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using System; +using System.Collections; using System.Collections.Generic; -using System.Formats.Asn1; +using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.X509; namespace Keyfactor.Extensions.Orchestrator.AEMCM.Logic { @@ -30,128 +42,90 @@ public sealed class SplitCertificate /// /// Splits a Keyfactor-supplied PKCS#12/PFX into leaf certificate, PKCS#8 (unencrypted) /// private key, and chain WITHOUT the leaf — the exact shape Cloud Manager requires. - /// Depends only on the BCL; deliberately free of any Keyfactor types so it is unit testable. + /// Uses BouncyCastle so key export does not depend on the OS key store or Windows CNG + /// export policy. Free of Keyfactor types so it is unit testable. /// public static class PfxSplitter { - private const string SubjectAltNameOid = "2.5.29.17"; - public static SplitCertificate Split(byte[] pfxBytes, string? password) { if (pfxBytes == null || pfxBytes.Length == 0) throw new ArgumentException("PFX content is empty.", nameof(pfxBytes)); -#if NET9_0_OR_GREATER - var collection = X509CertificateLoader.LoadPkcs12Collection( - pfxBytes, password, X509KeyStorageFlags.Exportable); -#else - var collection = new X509Certificate2Collection(); - collection.Import(pfxBytes, password, X509KeyStorageFlags.Exportable); -#endif + var store = new Pkcs12StoreBuilder().Build(); + using (var ms = new MemoryStream(pfxBytes)) + { + store.Load(ms, (password ?? string.Empty).ToCharArray()); + } - X509Certificate2? leaf = FindLeaf(collection); - if (leaf == null) - throw new InvalidOperationException("PFX did not contain a certificate with a private key."); + var keyAlias = store.Aliases.FirstOrDefault(store.IsKeyEntry) + ?? throw new InvalidOperationException("PFX did not contain a private key entry."); - var (algorithm, keySize, pkcs8) = ExportPrivateKey(leaf); + var privateKey = store.GetKey(keyAlias).Key; + var (algorithm, keySize) = DescribeKey(privateKey); - var chainCerts = collection - .Cast() - .Where(c => !c.RawData.SequenceEqual(leaf.RawData)) - .OrderBy(IsRootCertificate) // intermediates before any root - .ToList(); + var chainEntries = store.GetCertificateChain(keyAlias); + X509Certificate leaf; + var intermediates = new List(); - var chainPem = string.Join( - "\n", - chainCerts.Select(c => ToPem("CERTIFICATE", c.RawData))); + if (chainEntries != null && chainEntries.Length > 0) + { + leaf = chainEntries[0].Certificate; // leaf first + intermediates.AddRange(chainEntries.Skip(1).Select(e => e.Certificate)); // leaf EXCLUDED + } + else + { + leaf = store.GetCertificate(keyAlias).Certificate; + } + + var pkcs8Der = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey).GetDerEncoded(); return new SplitCertificate { - CertificatePem = ToPem("CERTIFICATE", leaf.RawData), - PrivateKeyPkcs8Pem = ToPem("PRIVATE KEY", pkcs8), - ChainPem = chainPem, - CommonName = leaf.GetNameInfo(X509NameType.SimpleName, forIssuer: false) ?? string.Empty, - SubjectAlternativeNames = ReadDnsSans(leaf), + CertificatePem = ToPem("CERTIFICATE", leaf.GetEncoded()), + PrivateKeyPkcs8Pem = ToPem("PRIVATE KEY", pkcs8Der), + ChainPem = string.Join("\n", intermediates.Select(c => ToPem("CERTIFICATE", c.GetEncoded()))), + CommonName = GetCommonName(leaf), + SubjectAlternativeNames = GetDnsSans(leaf), KeyAlgorithm = algorithm, KeySize = keySize, }; } - private static X509Certificate2? FindLeaf(X509Certificate2Collection collection) + private static (string algorithm, int keySize) DescribeKey(AsymmetricKeyParameter key) => key switch { - // Prefer an end-entity (non-CA) cert that has the private key. - var withKey = collection.Cast().Where(c => c.HasPrivateKey).ToList(); - if (withKey.Count == 0) return null; - return withKey.FirstOrDefault(c => !IsCaCertificate(c)) ?? withKey[0]; - } + RsaKeyParameters rsa => ("RSA", rsa.Modulus.BitLength), + ECPrivateKeyParameters ec => ("ECDSA", ec.Parameters.N.BitLength), + _ => throw new InvalidOperationException( + "Leaf certificate uses an unsupported private key algorithm (expected RSA or ECDSA)."), + }; - private static (string algorithm, int keySize, byte[] pkcs8) ExportPrivateKey(X509Certificate2 leaf) + private static string GetCommonName(X509Certificate cert) { - using var rsa = leaf.GetRSAPrivateKey(); - if (rsa != null) - return ("RSA", rsa.KeySize, rsa.ExportPkcs8PrivateKey()); - - using var ecdsa = leaf.GetECDsaPrivateKey(); - if (ecdsa != null) - return ("ECDSA", ecdsa.KeySize, ecdsa.ExportPkcs8PrivateKey()); - - throw new InvalidOperationException( - "Leaf certificate uses an unsupported private key algorithm (expected RSA or ECDSA)."); - } - - private static bool IsCaCertificate(X509Certificate2 cert) - { - foreach (var ext in cert.Extensions) - { - if (ext is X509BasicConstraintsExtension bc) - return bc.CertificateAuthority; - } - return false; + var values = cert.SubjectDN.GetValueList(X509Name.CN); + return values.Count > 0 ? values[0]?.ToString() ?? string.Empty : string.Empty; } - // Sort key: root certs (self-issued) come last in the chain output. - private static bool IsRootCertificate(X509Certificate2 cert) => - string.Equals(cert.SubjectName.RawData is { } s ? Convert.ToBase64String(s) : null, - cert.IssuerName.RawData is { } i ? Convert.ToBase64String(i) : null, - StringComparison.Ordinal); - - /// Parses dNSName entries from the SAN extension (DER) without locale-sensitive string parsing. - private static List ReadDnsSans(X509Certificate2 cert) + private static List GetDnsSans(X509Certificate cert) { var sans = new List(); - var ext = cert.Extensions[SubjectAltNameOid]; - if (ext == null) return sans; + var altNames = cert.GetSubjectAlternativeNames(); + if (altNames == null) return sans; - try + foreach (IList? entry in altNames) { - var reader = new AsnReader(ext.RawData, AsnEncodingRules.DER); - var sequence = reader.ReadSequence(); - while (sequence.HasData) + // Each entry is [ int tagType, object value ]; dNSName == GeneralName.DnsName (2). + if (entry is { Count: >= 2 } && entry[0] is int tag && tag == GeneralName.DnsName) { - var tag = sequence.PeekTag(); - // GeneralName CHOICE: dNSName is context-specific [2], IA5String. - if (tag.TagClass == TagClass.ContextSpecific && tag.TagValue == 2) - { - var dns = sequence.ReadCharacterString( - UniversalTagNumber.IA5String, - new Asn1Tag(TagClass.ContextSpecific, 2)); - if (!string.IsNullOrWhiteSpace(dns)) sans.Add(dns); - } - else - { - sequence.ReadEncodedValue(); // skip other GeneralName choices - } + var value = entry[1]?.ToString(); + if (!string.IsNullOrWhiteSpace(value)) sans.Add(value!); } } - catch (AsnContentException) - { - // Malformed SAN extension — return whatever we parsed rather than failing the whole job. - } return sans; } private static string ToPem(string label, byte[] der) => - new string(PemEncoding.Write(label, der)); + new string(System.Security.Cryptography.PemEncoding.Write(label, der)); } } diff --git a/AEMCM.Orchestrator/PamUtilities.cs b/AEMCM.Orchestrator/PamUtilities.cs index 5009023..4329a97 100644 --- a/AEMCM.Orchestrator/PamUtilities.cs +++ b/AEMCM.Orchestrator/PamUtilities.cs @@ -1,3 +1,11 @@ + +// Copyright 2026 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + using Keyfactor.Orchestrators.Extensions.Interfaces; using Microsoft.Extensions.Logging; diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..375b336 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +- 1.0.0 + - Initial release of the Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension. + - Certificate Store Type `AEMCM`; one certificate store maps to one Cloud Manager program (`programId`). + - Supported job types: Inventory, Management (Add/Remove), and Discovery. + - Authenticates to the Adobe Cloud Manager API using Adobe IMS OAuth Server-to-Server credentials (client credentials); access tokens are cached and refreshed automatically. + - Inventory pages through all certificates in a program and reports every certificate — including Adobe-managed (DV) and expired certificates — so the 70-certificate program limit is visible. + - Management Add splits the supplied PKCS#12 into leaf certificate, unencrypted PKCS#8 private key, and intermediate chain (leaf excluded), using BouncyCastle so key export does not depend on the OS key store. + - Management Add prefers updating an existing certificate (matched by alias or identical SAN set) over creating a new one, to conserve the 70-certificate-per-program budget; validates key type (RSA-2048, EC secp256r1/secp384r1) and the 100-SAN limit before upload. + - Management Remove blocks deletion of a certificate that is still referenced by a domain mapping, and refuses to modify or delete Adobe-managed (DV) certificates. + - The certificate alias is the Adobe certificate name (Custom Alias required); name uniqueness is enforced on Add so the alias round-trips with inventory. + - Discovery enumerates programs per IMS Org ID (supplied in the discovery "Directories to search" field) via the tenant-scoped endpoints and returns each `programId` as a discoverable store path. + - PAM support for store credentials and secret custom fields. diff --git a/README.md b/README.md index 1b8a530..d12c127 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,455 @@ -# Adobe Experience Manager (Cloud Manager) Orchestrator - -A Keyfactor Universal Orchestrator extension that manages customer-managed (OV/EV) TLS/SSL -certificates on **Adobe Experience Manager as a Cloud Service** through the **Adobe Cloud Manager API**. - -Supported job types: **Inventory**, **Management (Add / Remove)**, **Discovery**. - -> Scaffold / prototype. The endpoints and payloads are modeled directly on the Cloud Manager -> OpenAPI spec (`api.yaml`). See open items in [`docs/DESIGN.md` §8](#design) before production use. -> `docs/DESIGN.md` is intentionally not committed here; keep it wherever you track design notes. - -## Store type short name - -`AEMCM` — see `integration-manifest.json` for the full Certificate Store Type definition -(create it in Command with `kfutil store-types create` or by hand). - -| Store field | Meaning | -|---|---| -| Client Machine | Cloud Manager base URL (`https://cloudmanager.adobe.io`) | -| Store Path | Numeric Cloud Manager **programId** (one store = one program) | -| Server Username | IMS Client ID (API key) | -| Server Password | IMS Client Secret | -| `ImsOrgId` (custom field, secret) | Adobe IMS Org ID → `x-gw-ims-org-id` | -| `ImsTokenUrl` / `ImsScopes` (custom fields) | IMS OAuth Server-to-Server token endpoint / scopes | - -## Key platform constraints (drive the logic) - -- Max **70** certificates per program (incl. Adobe-managed DV and expired) → Management prefers - **update over add** and reports all certs in Inventory. -- Max **100 SANs** per certificate. -- Customer-managed certs must be **OV/EV**, PEM, private key **PKCS#8 unencrypted**, RSA-2048 or - EC secp256r1/secp384r1. -- The leaf certificate must **not** appear in the chain field (handled by `PfxSplitter`). -- A cert with active domain mappings cannot be deleted (handled by Remove's safe-delete check). - -## Project layout - -Follows the standard Keyfactor UO extension layout (cf. `azurekeyvault-orchestrator`): a `Jobs/` -folder with an abstract base class the jobs inherit, plus the client, properties, and helpers at -the project root. - -``` -AEMCM.Orchestrator/ class library (net6.0;net8.0;net10.0) - Jobs/ - AemcmJob.cs abstract base : IOrchestratorJobExtension (InitializeStore, shared state) - Inventory.cs : AemcmJob, IInventoryJobExtension - Management.cs : AemcmJob, IManagementJobExtension - Discovery.cs : AemcmJob, IDiscoveryJobExtension - Client/ IMS auth + Cloud Manager client (+ interfaces) + API models - Logic/ PfxSplitter, CertMatcher, BudgetManager (pure, unit-tested) - AemcmProperties.cs resolved connection/config + store custom fields - Constants.cs store type name + defaults - JobAttribute.cs [Job(...)] marker + JobTypes - PamUtilities.cs PAM secret resolution - manifest.json capability → class registration -AEMCM.Orchestrator.Tests/ xUnit tests for the Logic + Discovery parsing -integration-manifest.json store-type definition (also copied to build output) -api.yaml Cloud Manager OpenAPI spec (reference) -``` - -Jobs are constructed with an `IPAMSecretResolver` (injected by the orchestrator) and call -`InitializeStore(config)` on the base class, which resolves credentials, parses the store path -(`programId`) and custom fields, and builds the IMS auth + Cloud Manager clients. - -## Building - -Keyfactor packages are on GitHub Packages. Configure the feed credential once (a GitHub PAT with -`read:packages`), then restore/build/test: - -```bash -dotnet nuget add source https://nuget.pkg.github.com/Keyfactor/index.json \ - --name keyfactor-github --username --password --store-password-in-clear-text - -dotnet restore -dotnet build -c Release -dotnet test -``` - -> Pin `Keyfactor.Orchestrators.IOrchestratorJobExtensions` / `Keyfactor.Logging` in -> `AEMCM.Orchestrator.csproj` to the versions matching your target Universal Orchestrator release. - -## Deploying - -Copy the build output (DLLs + `manifest.json` + `integration-manifest.json` + dependencies) into a -subfolder of the orchestrator's `extensions/` directory and restart the orchestrator service. - - -## Design - -Full design — API mapping, auth, job flows, SAN-consolidation decision tree, error handling, and -open questions — lives in `docs/DESIGN.md`. +

+ Adobe Experience Manager (Cloud Manager) Universal Orchestrator Extension +

+ +

+ +Integration Status: production +Release +Issues +GitHub Downloads (all assets, all releases) +

+ +

+ + + Support + + · + + Installation + + · + + License + + · + + Related Integrations + +

+ +## Overview + +The Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension enables Keyfactor Command to +remotely manage customer-managed (OV/EV) TLS/SSL certificates on **Adobe Experience Manager as a Cloud Service** +(AEMaaCS) through the **Adobe Cloud Manager API**. These certificates secure custom domains served by AEMaaCS. +The extension supports inventory, enrollment (add), removal, and discovery. + +In Cloud Manager, certificates are scoped to a **program**, so a certificate store of the `AEMCM` store type +represents a single Cloud Manager program (the store's Store Path is the numeric `programId`), and every +certificate in that program is managed through that one store. + +Two platform caveats are worth calling out up front: Cloud Manager enforces a hard limit of **70 installed +certificates per program** (including Adobe-managed DV certificates and expired certificates) and up to +**100 SANs per certificate**; and Adobe-managed (DV) certificates are **read-only** to this extension, which +manages only customer-managed (OV/EV) certificates. Because of the 70-certificate limit, the extension prefers +updating an existing certificate over creating a new one. + +## Compatibility + +This integration is compatible with Keyfactor Universal Orchestrator version 10.4 and later. + +## Support + +The Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension is supported by Keyfactor. If you require support for any issues or have feature request, please open a support ticket by either contacting your Keyfactor representative or via the Keyfactor Support Portal at https://support.keyfactor.com. + +> If you want to contribute bug fixes or additional enhancements, use the **[Pull requests](../../pulls)** tab. + +## Requirements & Prerequisites + +Before installing the Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension, we recommend that you install [kfutil](https://github.com/Keyfactor/kfutil). Kfutil is a command-line tool that simplifies the process of creating store types, installing extensions, and instantiating certificate stores in Keyfactor Command. + +### Configure Adobe Cloud Manager API access + +The extension authenticates to the Cloud Manager API with an Adobe IMS **OAuth Server-to-Server** credential +(Adobe has deprecated JWT authentication; it is not used). + +1. In the [Adobe Developer Console](https://developer.adobe.com/console), create (or open) a project and add the + **Cloud Manager API**, choosing the **OAuth Server-to-Server** credential type. +2. Assign the credential a product profile / role with permission to manage Cloud Manager SSL certificates — the + **Business Owner** or **Deployment Manager** role. +3. Record the **Client ID**, **Client Secret**, and **IMS Organization ID**; these are entered on the certificate + store (or discovery job) in Keyfactor Command. + +> :warning: A credential without the **Business Owner** or **Deployment Manager** role can authenticate but cannot +> add, update, or delete certificates. + +### Endpoint access / firewall + +The orchestrator host needs outbound access to: + +- The Keyfactor Command instance +- `ims-na1.adobelogin.com` — Adobe IMS token endpoint (to obtain the bearer access token) +- `cloudmanager.adobe.io` — the Cloud Manager API (inventory, add, remove, and discovery operations) + +### Certificate requirements + +Customer-managed certificates must meet Cloud Manager's requirements. The extension performs best-effort +client-side validation and Cloud Manager enforces the rest server-side: + +- **OV or EV** certificates from a trusted CA. DV and self-signed certificates are not supported for + customer-managed upload. +- Private key in **PKCS#8**, unencrypted. Supported key types: **RSA-2048**, or Elliptic Curve + **secp256r1 (prime256v1)** / **secp384r1**. RSA-3072/4096 are not supported by Cloud Manager. +- Up to **100 SANs** per certificate. + +The extension automatically splits the PKCS#12 supplied by Command into the leaf certificate, the unencrypted +PKCS#8 private key, and the intermediate chain **with the leaf excluded** (Cloud Manager rejects uploads that +include the leaf in the chain). + +## AEMCM Certificate Store Type + +To use the Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension, you **must** create the AEMCM Certificate Store Type. This only needs to happen _once_ per Keyfactor Command instance. + +The `AEMCM` certificate store type represents a single **Adobe Cloud Manager program**. When you define a +certificate store of this type, its Store Path is the numeric `programId`, and the store manages every +customer-managed (OV/EV) SSL certificate in that program through the Cloud Manager API. + +The certificate **alias is the Adobe certificate name**. It is supplied at enrollment, stored as the certificate's +name in Cloud Manager, and reported back by inventory, so aliases round-trip between enrollment and inventory. Name +uniqueness within a program is enforced on enrollment. + +Caveats specific to this store type: + +- A program is limited to **70 installed certificates** (including Adobe-managed DV and expired certificates) and + each certificate to **100 SANs**. To conserve this budget the extension updates an existing certificate when it + can, rather than creating duplicates. +- Adobe-managed (DV) certificates are **read-only**; the extension will not modify or remove them. + +#### Adobe Experience Manager Cloud Manager Requirements + +Before creating certificate stores of this type: + +1. Configure an Adobe IMS **OAuth Server-to-Server** credential with the **Business Owner** or **Deployment + Manager** role, as described in the extension-wide Requirements section. +2. Record the credential's **Client ID**, **Client Secret**, and **IMS Organization ID**. +3. Identify the Cloud Manager **`programId`** for each program you intend to manage (a Discovery job can find these + for you). + +Credentials map to the store fields as follows: **Server Username** = IMS Client ID, **Server Password** = IMS +Client Secret, and the **IMS Organization ID** custom field = your IMS Org ID. + +#### Supported Operations + +| Operation | Is Supported | +|--------------|--------------| +| Add | ✅ Checked | +| Remove | ✅ Checked | +| Discovery | ✅ Checked | +| Reenrollment | 🔲 Unchecked | +| Create | 🔲 Unchecked | + +#### Store Type Creation + +##### Using kfutil: +`kfutil` is a custom CLI for the Keyfactor Command API and can be used to create certificate store types. +For more information on [kfutil](https://github.com/Keyfactor/kfutil) check out the [docs](https://github.com/Keyfactor/kfutil?tab=readme-ov-file#quickstart) + +
Click to expand AEMCM kfutil details + + ##### Using online definition from GitHub: + This will reach out to GitHub and pull the latest store-type definition + ```shell + # Adobe Experience Manager Cloud Manager + kfutil store-types create AEMCM + ``` + + ##### Offline creation using integration-manifest file: + If required, it is possible to create store types from the [integration-manifest.json](./integration-manifest.json) included in this repo. + You would first download the [integration-manifest.json](./integration-manifest.json) and then run the following command + in your offline environment. + ```shell + kfutil store-types create --from-file integration-manifest.json + ``` +
+ +#### Manual Creation +Below are instructions on how to create the AEMCM store type manually in +the Keyfactor Command Portal + +
Click to expand manual AEMCM details + + Create a store type called `AEMCM` with the attributes in the tables below: + + ##### Basic Tab + | Attribute | Value | Description | + | --------- | ----- | ----- | + | Name | Adobe Experience Manager Cloud Manager | Display name for the store type (may be customized) | + | Short Name | AEMCM | Short display name for the store type | + | Capability | AEMCM | Store type name orchestrator will register with. Check the box to allow entry of value | + | Supports Add | ✅ Checked | Indicates that the Store Type supports Management Add | + | Supports Remove | ✅ Checked | Indicates that the Store Type supports Management Remove | + | Supports Discovery | ✅ Checked | Indicates that the Store Type supports Discovery | + | Supports Reenrollment | 🔲 Unchecked | Indicates that the Store Type supports Reenrollment | + | Supports Create | 🔲 Unchecked | Indicates that the Store Type supports store creation | + | Needs Server | ✅ Checked | Determines if a target server name is required when creating store | + | Blueprint Allowed | 🔲 Unchecked | Determines if store type may be included in an Orchestrator blueprint | + | Uses PowerShell | 🔲 Unchecked | Determines if underlying implementation is PowerShell | + | Requires Store Password | 🔲 Unchecked | Enables users to optionally specify a store password when defining a Certificate Store. | + | Supports Entry Password | 🔲 Unchecked | Determines if an individual entry within a store can have a password. | + + The Basic tab should look like this: + + ![AEMCM Basic Tab](docsource/images/AEMCM-basic-store-type-dialog.svg) + + ##### Advanced Tab + | Attribute | Value | Description | + | --------- | ----- | ----- | + | Supports Custom Alias | Required | Determines if an individual entry within a store can have a custom Alias. | + | Private Key Handling | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. | + | PFX Password Style | Default | 'Default' - PFX password is randomly generated, 'Custom' - PFX password may be specified when the enrollment job is created (Requires the Allow Custom Password application setting to be enabled.) | + + The Advanced tab should look like this: + + ![AEMCM Advanced Tab](docsource/images/AEMCM-advanced-store-type-dialog.svg) + + > For Keyfactor **Command versions 24.4 and later**, a Certificate Format dropdown is available with PFX and PEM options. Ensure that **PFX** is selected, as this determines the format of new and renewed certificates sent to the Orchestrator during a Management job. Currently, all Keyfactor-supported Orchestrator extensions support only PFX. + + ##### Custom Fields Tab + Custom fields operate at the certificate store level and are used to control how the orchestrator connects to the remote target server containing the certificate store to be managed. The following custom fields should be added to the store type: + + | Name | Display Name | Description | Type | Default Value/Options | Required | + | ---- | ------------ | ---- | --------------------- | -------- | ----------- | + | ImsOrgId | IMS Organization ID | The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential. | String | | ✅ Checked | + | ImsTokenUrl | IMS Token Endpoint | The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens. | String | https://ims-na1.adobelogin.com/ims/token/v3 | ✅ Checked | + | ImsScopes | IMS Scopes | Comma-separated IMS scopes requested for the access token. | String | openid,AdobeID,read_organizations,additional_info.projectedProductContext | ✅ Checked | + + The Custom Fields tab should look like this: + + ![AEMCM Custom Fields Tab](docsource/images/AEMCM-custom-fields-store-type-dialog.svg) + + ###### IMS Organization ID + The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential. + + ![AEMCM Custom Field - ImsOrgId](docsource/images/AEMCM-custom-field-ImsOrgId-dialog.svg) + + + ###### IMS Token Endpoint + The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens. + + ![AEMCM Custom Field - ImsTokenUrl](docsource/images/AEMCM-custom-field-ImsTokenUrl-dialog.svg) + + + ###### IMS Scopes + Comma-separated IMS scopes requested for the access token. + + ![AEMCM Custom Field - ImsScopes](docsource/images/AEMCM-custom-field-ImsScopes-dialog.svg) + + +
+ +## Installation + +1. **Download the latest Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension from GitHub.** + + Navigate to the [Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension GitHub version page](https://github.com/Keyfactor/adobe-experience-manager-orchestrator/releases/latest). Refer to the compatibility matrix below to determine which asset should be downloaded. Then, click the corresponding asset to download the zip archive. + + | Universal Orchestrator Version | Latest .NET version installed on the Universal Orchestrator server | `rollForward` condition in `Orchestrator.runtimeconfig.json` | `adobe-experience-manager-orchestrator` .NET version to download | + | --------- | ----------- | ----------- | ----------- | + | Older than `11.0.0` | | | `net6.0` | + | Between `11.0.0` and `11.5.1` (inclusive) | `net6.0` | | `net6.0` | + | Between `11.0.0` and `11.5.1` (inclusive) | `net8.0` | `Disable` | `net6.0` | + | Between `11.0.0` and `11.5.1` (inclusive) | `net8.0` | `LatestMajor` | `net8.0` | + | `11.6` _and_ newer | `net8.0` | | `net8.0` | + | `25.5` _and_ newer | `net10.0` | | `net10.0` | + + Unzip the archive containing extension assemblies to a known location. + + > **Note** If you don't see an asset with a corresponding .NET version, you should always assume that it was compiled for `net10.0`. + +2. **Locate the Universal Orchestrator extensions directory.** + + * **Default on Windows** - `C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions` + * **Default on Linux** - `/opt/keyfactor/orchestrator/extensions` + +3. **Create a new directory for the Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension inside the extensions directory.** + + Create a new directory called `adobe-experience-manager-orchestrator`. + > The directory name does not need to match any names used elsewhere; it just has to be unique within the extensions directory. + +4. **Copy the contents of the downloaded and unzipped assemblies from __step 2__ to the `adobe-experience-manager-orchestrator` directory.** + +5. **Restart the Universal Orchestrator service.** + + Refer to [Starting/Restarting the Universal Orchestrator service](https://software.keyfactor.com/Core-OnPrem/Current/Content/InstallingAgents/NetCoreOrchestrator/StarttheService.htm). + +6. **(optional) PAM Integration** + + The Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension is compatible with all supported Keyfactor PAM extensions to resolve PAM-eligible secrets. PAM extensions running on Universal Orchestrators enable secure retrieval of secrets from a connected PAM provider. + + To configure a PAM provider, [reference the Keyfactor Integration Catalog](https://keyfactor.github.io/integrations-catalog/content/pam) to select an extension and follow the associated instructions to install it on the Universal Orchestrator (remote). + +> The above installation steps can be supplemented by the [official Command documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/InstallingAgents/NetCoreOrchestrator/CustomExtensions.htm?Highlight=extensions). + +## Post Installation + +After installing the extension DLLs on the orchestrator, create the `AEMCM` certificate store type in Keyfactor +Command — with [kfutil](https://github.com/Keyfactor/kfutil) (`kfutil store-types create AEMCM`) or manually from +`integration-manifest.json` — before defining any certificate stores. + +## Defining Certificate Stores + +### Store Creation + +#### Manually with the Command UI + +
Click to expand details + +1. **Navigate to the _Certificate Stores_ page in Keyfactor Command.** + + Log into Keyfactor Command, toggle the _Locations_ dropdown, and click _Certificate Stores_. + +2. **Add a Certificate Store.** + + Click the Add button to add a new Certificate Store. Use the table below to populate the **Attributes** in the **Add** form. + + | Attribute | Description | + | --------- | ----------- | + | Category | Select "Adobe Experience Manager Cloud Manager" or the customized certificate store name from the previous step. | + | Container | Optional container to associate certificate store with. | + | Client Machine | The Adobe Cloud Manager API base URL. Enter 'https://cloudmanager.adobe.io'. | + | Store Path | The numeric Cloud Manager program identifier (programId) that this store manages; for example, '12345'. One store maps to one program. | + | Orchestrator | Select an approved orchestrator capable of managing `AEMCM` certificates. Specifically, one with the `AEMCM` capability. | + | ImsOrgId | The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential. | + | ImsTokenUrl | The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens. | + | ImsScopes | Comma-separated IMS scopes requested for the access token. | + +
+ +#### Using kfutil CLI + +
Click to expand details + +1. **Generate a CSV template for the AEMCM certificate store** + + ```shell + kfutil stores import generate-template --store-type-name AEMCM --outpath AEMCM.csv + ``` +2. **Populate the generated CSV file** + + Open the CSV file, and reference the table below to populate parameters for each **Attribute**. + + | Attribute | Description | + | --------- | ----------- | + | Category | Select "Adobe Experience Manager Cloud Manager" or the customized certificate store name from the previous step. | + | Container | Optional container to associate certificate store with. | + | Client Machine | The Adobe Cloud Manager API base URL. Enter 'https://cloudmanager.adobe.io'. | + | Store Path | The numeric Cloud Manager program identifier (programId) that this store manages; for example, '12345'. One store maps to one program. | + | Orchestrator | Select an approved orchestrator capable of managing `AEMCM` certificates. Specifically, one with the `AEMCM` capability. | + | Properties.ImsOrgId | The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential. | + | Properties.ImsTokenUrl | The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens. | + | Properties.ImsScopes | Comma-separated IMS scopes requested for the access token. | + +3. **Import the CSV file to create the certificate stores** + + ```shell + kfutil stores import csv --store-type-name AEMCM --file AEMCM.csv + ``` + +
+ +#### PAM Provider Eligible Fields +
Attributes eligible for retrieval by a PAM Provider on the Universal Orchestrator + +If a PAM provider was installed _on the Universal Orchestrator_ in the [Installation](#Installation) section, the following parameters can be configured for retrieval _on the Universal Orchestrator_. + + | Attribute | Description | + | --------- | ----------- | + | ServerUsername | Username to use when connecting to server | + | ServerPassword | Password to use when connecting to server | + +Please refer to the **Universal Orchestrator (remote)** usage section ([PAM providers on the Keyfactor Integration Catalog](https://keyfactor.github.io/integrations-catalog/content/pam)) for your selected PAM provider for instructions on how to load attributes orchestrator-side. +> Any secret can be rendered by a PAM provider _installed on the Keyfactor Command server_. The above parameters are specific to attributes that can be fetched by an installed PAM provider running on the Universal Orchestrator server itself. + +
+ +> The content in this section can be supplemented by the [official Command documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/Certificate%20Stores.htm?Highlight=certificate%20store). + +### Certificate Operations + +#### Inventory + +Inventory pages through all certificates in the program and reports every one — including Adobe-managed (DV) and +expired certificates — so the 70-certificate limit is visible. Certificate type, status, common name, SANs, and +expiration are surfaced as entry parameters. DV certificates are reported read-only. + +#### Add / Enrollment + +Provide an alias; it becomes the Adobe certificate name. Enrolling a name that already exists in the program +**fails unless _Overwrite_ is enabled**, in which case the matching certificate is updated in place. To conserve +the 70-certificate budget, an incoming certificate that matches an existing one by alias or by an identical SAN set +updates that certificate rather than creating a duplicate. If the program is at the 70-certificate limit and no +existing certificate matches, the job fails with guidance to remove expired or unused certificates. Key type +(RSA-2048 or EC secp256r1/secp384r1) and the 100-SAN limit are validated before upload. + +#### Remove + +Removing a certificate deletes it from the program. If the certificate is still referenced by one or more domain +mappings, the job fails and lists the offending mapping(s) — remove the mapping(s) first, then retry, and run the +pipeline afterward to fully undeploy. Adobe-managed (DV) certificates cannot be removed. + +### Domain Mappings and Certificate Bindings + +In Cloud Manager, a certificate only serves live traffic once a **domain mapping** (CDN configuration) +associates a domain with it. This extension manages **certificates only** — it does not create, update, or +delete domain mappings. Bindings are managed in Cloud Manager (or through the Cloud Manager domain-mapping APIs) +outside of Keyfactor. This has several implications worth understanding: + +- **Enrollment installs a certificate; it does not bind it.** Adding a certificate uploads it to the program and + makes it available, but does not attach it to any domain. Until a domain mapping pointing at the certificate is + created in Cloud Manager, the certificate is installed but not serving traffic. + +- **Renew with _Overwrite_ to preserve existing bindings.** Renewing or replacing a certificate with _Overwrite_ + enabled updates it **in place** — the Cloud Manager certificate id does not change — so any existing domain + mappings continue to point at the renewed certificate automatically, with no re-mapping required. This is the + recommended renewal workflow. + +- **A brand-new certificate is not automatically adopted by existing domains.** If you enroll a *new* certificate + (a new alias / name) instead of overwriting, existing domain mappings continue to reference the previous + certificate. Re-point the mapping(s) to the new certificate in Cloud Manager before retiring the old one. + (Cloud Manager's own behavior is that when multiple SAN certificates cover the same domain, the most recently + updated/deployed certificate is served for that domain.) + +- **A bound certificate cannot be removed.** A Remove job fails if the target certificate is still referenced by + one or more domain mappings; the failure message lists the mapping(s). Remove or re-point those mappings in + Cloud Manager, then re-run the Remove job. Certificates with no domain mappings delete cleanly (run the pipeline + afterward to fully undeploy). + +> Managing certificate-to-domain bindings from Keyfactor is intentionally out of scope for this release. The Cloud +> Manager domain-mapping APIs support full create/update/delete, so this could be added later (for example, via +> entry parameters) if it becomes a requirement. + +### Certificate Enrollment Alias Requirements + +The alias is the Adobe certificate name and must be unique within the program. Use **Overwrite** to renew or +replace an existing certificate (matched by that name). Certificates created outside Keyfactor that happen to share +a name are surfaced during inventory as `name (id)` so aliases remain unique. + +## Discovering Certificate Stores with the Discovery Job + +### Adobe Experience Manager Cloud Manager Discovery Job + +Discovery enumerates the Cloud Manager programs your credential can access and returns each as a discoverable +store path (a `programId`). + +Because a Discovery job has no certificate store, the store's custom fields (including the IMS Org ID) are not +available on the discovery form. Provide the Org ID(s) through the standard discovery fields instead: + +- **Client Machine**: the Cloud Manager base URL, `https://cloudmanager.adobe.io`. +- **Server Username / Password**: the IMS Client ID / Client Secret. +- **Directories to Search**: one or more **comma-separated IMS Organization IDs**. This field is required — with no + value the job cannot determine which organization's tenants and programs to enumerate. + +For each Org ID, the job lists the organization's tenants (`GET /api/tenants`) and then each tenant's programs +(`GET /api/tenant/{tenantId}/programs`), returning every `programId`. Approve a result to create an `AEMCM` +certificate store for that program. + + +## License + +Apache License 2.0, see [LICENSE](LICENSE). + +## Related Integrations + +See all [Keyfactor Universal Orchestrator extensions](https://github.com/orgs/Keyfactor/repositories?q=orchestrator). diff --git a/api.yaml b/api.yaml deleted file mode 100644 index 9ef62b7..0000000 --- a/api.yaml +++ /dev/null @@ -1,8481 +0,0 @@ -swagger: '2.0' -info: - version: 1.0.0 - title: Cloud Manager API - description: 'This API allows access to Cloud Manager programs, pipelines, and environments by an authorized technical account created through the Adobe I/O Console. The base url for this API is https://cloudmanager.adobe.io, e.g. to get the list of programs for an organization, you would make a GET request to https://cloudmanager.adobe.io/api/programs (with the correct set of headers as described below). This swagger file can be downloaded from https://raw.githubusercontent.com/AdobeDocs/cloudmanager-api-docs/main/swagger-specs/api.yaml.' -host: cloudmanager.adobe.io -schemes: - - https -consumes: - - application/json -produces: - - application/json -tags: - - name: Programs - - name: Repositories - - name: Branches - - name: Pipelines - - name: Pipeline Execution - - name: Execution Artifacts - - name: Environments - - name: Region Deployments - - name: Variables - - name: Rapid Development Environments - - name: Environment Restore From Backup - - name: IP Allowlist - - name: IP Allowlist Binding - - name: Domain - - name: Domain Mappings - CDN Configurations - - name: SSL Certificates - - name: EDS Sites - - name: Tenants - - name: Regions - - name: Network infrastructure - - name: Environment Advanced Networking Configuration - - name: ContentSets -paths: - /api/programs: - get: - tags: - - Programs - summary: Lists Programs - description: 'This API is deprecated and should no longer be used. Please use the [Lists Programs for Tenant API](#operation/getProgramsForTenant) instead.' - operationId: getPrograms - parameters: - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/ProgramList' - '/api/program/{programId}': - get: - tags: - - Programs - summary: Get Program - description: Returns a program by its id - operationId: getProgram - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of program - schema: - $ref: '#/definitions/Program' - '404': - description: Program not found - delete: - tags: - - Programs - summary: Delete Program - description: Delete an program - operationId: deleteProgram - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Program' - '202': - description: Delete was successful. - schema: - $ref: '#/definitions/Program' - '403': - description: Forbidden. - '404': - description: Program not found. - '412': - description: Deletion not supported - '/api/program/{programId}/repositories': - get: - tags: - - Repositories - summary: Lists Repositories - description: Lists all Repositories in an program - operationId: getRepositories - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: start - in: query - description: Pagination start parameter - required: false - type: string - default: '0' - - name: limit - in: query - description: Pagination limit parameter - required: false - type: integer - default: 20 - format: int32 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/RepositoryList' - '/api/program/{programId}/repository/{repositoryId}': - get: - tags: - - Repositories - summary: Get Repository - description: Returns an repository by its id - operationId: getRepository - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: repositoryId - in: path - description: Identifier of the repository - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Repository' - '/api/program/{programId}/repository/{repositoryId}/branches': - get: - tags: - - Branches - summary: List Branches - description: Returns the list of branches from a repository - operationId: getBranches - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: repositoryId - in: path - description: Identifier of the repository - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of the list of repository branches - schema: - $ref: '#/definitions/BranchList' - '/api/program/{programId}/pipelines': - get: - tags: - - Pipelines - summary: List Pipelines - description: Returns all the pipelines that the requesting user has access to in an program - operationId: getPipelines - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: type - in: query - description: Type of the pipelines - required: false - type: string - - name: start - in: query - description: Pagination start parameter - required: false - type: string - default: '0' - - name: limit - in: query - description: Pagination limit parameter - required: false - type: integer - default: 500 - format: int32 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/PipelineList' - '/api/program/{programId}/pipeline/{pipelineId}': - get: - tags: - - Pipelines - summary: Get Pipeline - description: Returns a pipeline by its id - operationId: getPipeline - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of pipeline - schema: - $ref: '#/definitions/Pipeline' - '404': - description: Pipeline not found - delete: - tags: - - Pipelines - summary: Delete a Pipeline - description: Delete a pipeline. All the data is wiped. - operationId: deletePipeline - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - default: - description: successful operation - patch: - tags: - - Pipelines - summary: Patches Pipeline - description: Patches a pipeline within an program. - operationId: patchPipeline - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - in: body - name: body - description: The update to the pipeline - required: true - schema: - $ref: '#/definitions/PipelineUpdate' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Pipeline' - '/api/program/{programId}/pipeline/{pipelineId}/cache': - delete: - tags: - - Pipelines - summary: Invalidate Cache - description: Remove all cached artifacts and resets the cache to an empty state. - operationId: invalidateCache - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - default: - description: successful operation - '/api/program/{programId}/pipeline/{pipelineId}/execution': - get: - tags: - - Pipeline Execution - summary: Get current pipeline execution - description: Returns current pipeline execution if any. - operationId: getCurrentExecution - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of current execution - schema: - $ref: '#/definitions/PipelineExecution' - '404': - description: No pipeline execution exits or unknown pipeline or program - put: - tags: - - Pipeline Execution - summary: Start the pipeline - description: Starts the Pipeline. This works only if the pipeline is not already started. - operationId: startPipeline - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: pipelineExecutionMode - in: query - description: The mode in which to run the execution. EMERGENCY mode will skip certain steps and is only available to select AMS customers. - required: false - type: string - default: NORMAL - enum: - - NORMAL - - EMERGENCY - - name: stepId - in: query - description: Identifier of the step from which the re-execution will start - required: false - type: string - - name: sourceExecutionId - in: query - description: Identifier of the source execution from which the execution will start - required: false - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Successfully started pipeline execution - schema: - $ref: '#/definitions/PipelineExecution' - headers: - location: - type: string - description: The URL of the new execution - '400': - description: Request conflicts with the expected state of pipeline - '404': - description: No pipeline execution exits or unknown pipeline or application - '412': - description: Pipeline is busy - '503': - description: Pipeline execution cannot be started because of unplanned maintenance - schema: - $ref: '#/definitions/SystemUnderMaintenanceExceptionMapper' - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}': - get: - tags: - - Pipeline Execution - summary: Get pipeline execution - description: Returns a pipeline execution by id - operationId: getExecution - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of execution - schema: - $ref: '#/definitions/PipelineExecution' - '404': - description: No pipeline execution exits or unknown pipeline or application - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}': - get: - tags: - - Pipeline Execution - summary: Get step state - description: '' - operationId: stepState - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of step state - schema: - $ref: '#/definitions/PipelineExecutionStepState' - '403': - description: Missing permission for user to read step - '404': - description: Pipeline execution does not exist - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}/advance': - put: - tags: - - Pipeline Execution - summary: Advance - description: 'Post to this url in order to advance the current pipeline execution, if paused and waiting for user interaction. Link is present in output only in that case. The input depends on the actual reason for which the pipeline execution stopped.' - operationId: advancePipelineExecution - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - in: body - name: body - description: 'Input for advance. See documentation at https://www.adobe.io/experience-cloud/cloud-manager/guides/api-usage/advancing-and-cancelling-steps/ for details.' - required: true - schema: - type: object - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '202': - description: Successful resume of pipeline execution - '403': - description: Missing permission for user to advance the pipeline execution - '404': - description: No pipeline execution exits or unknown pipeline or program - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}/cancel': - put: - tags: - - Pipeline Execution - summary: Cancel - description: Post to this url in order to cancel the current pipeline execution. Link is present in output only in that case. - operationId: cancelPipelineExecutionStep - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - in: body - name: body - description: 'Input for cancel. See documentation at https://www.adobe.io/experience-cloud/cloud-manager/guides/api-usage/advancing-and-cancelling-steps/ for details.' - required: true - schema: - type: object - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '202': - description: Successful cancel of pipeline execution - '403': - description: Missing permission for user to cancel the current pipeline execution - '404': - description: No pipeline execution exits or unknown pipeline or program - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}/logs': - get: - tags: - - Pipeline Execution - summary: Get logs - description: Get the logs associated with a step. - operationId: getStepLogs - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - name: file - in: query - description: Identifier of the log file - required: false - type: string - - name: Accept - in: header - required: false - type: string - description: 'Specify application/json in this header to receive a JSON response. Otherwise, a 307 response code will be returned with a Location header.' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of logs - schema: - $ref: '#/definitions/Redirect' - '403': - description: Missing permission for user to read logs - '404': - description: Pipeline execution does not exist - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}/artifacts': - get: - tags: - - Execution Artifacts - summary: ListArtifacts - description: Get the list of artifacts associated with a step. - operationId: listStepArtifacts - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of artifacts list - schema: - $ref: '#/definitions/ArtifactList' - '403': - description: Missing permission for user to read artifacts - '404': - description: Pipeline execution does not exist - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}/artifact/{artifactId}': - get: - tags: - - Execution Artifacts - summary: GetArtifact - description: Get artifact. - operationId: getStepArtifact - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - name: artifactId - in: path - description: Identifier of the artifact - required: true - type: string - - name: Accept - in: header - required: false - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of artifact - '403': - description: Missing permission for user to read artifact - '404': - description: Pipeline execution does not exist - '/api/program/{programId}/pipeline/{pipelineId}/execution/{executionId}/phase/{phaseId}/step/{stepId}/metrics': - get: - tags: - - Pipeline Execution - summary: Get step metrics - description: '' - operationId: stepMetric - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: executionId - in: path - description: Identifier of the execution - required: true - type: string - - name: phaseId - in: path - description: Identifier of the phase - required: true - type: string - - name: stepId - in: path - description: Identifier of the step - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of metrics - schema: - $ref: '#/definitions/PipelineStepMetrics' - '403': - description: Missing permission for user to read metrics - '404': - description: Pipeline execution does not exist - '/api/program/{programId}/pipeline/{pipelineId}/executions': - get: - tags: - - Pipeline Execution - summary: List Executions - description: Returns the history of pipeline executions in a newest to oldest order - operationId: getExecutions - parameters: - - name: programId - in: path - description: Identifier of the program. - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - name: start - in: query - description: Pagination start parameter - required: false - type: string - - name: limit - in: query - description: Pagination limit parameter - required: false - type: integer - format: int32 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of execution history - schema: - $ref: '#/definitions/PipelineExecutionListRepresentation' - '403': - description: Missing permission for user to read executions - '404': - description: Pipeline does not exist - '/api/program/{programId}/environments': - get: - tags: - - Environments - summary: List Environments - description: Lists all environments in an program - operationId: getEnvironments - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: type - in: query - description: Type of the environment - required: false - type: string - enum: - - dev - - stage - - prod - - rde - - preprod - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of environment list - schema: - $ref: '#/definitions/EnvironmentList' - '404': - description: Program not found - post: - tags: - - Environments - summary: Create or clone Environment - description: Create Environment - operationId: createEnvironment - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - in: body - name: body - description: Environment - required: true - schema: - $ref: '#/definitions/NewEnvironment' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Environment created - schema: - $ref: '#/definitions/Environment' - '400': - description: Bad request - '/api/program/{programId}/environment/{environmentId}': - get: - tags: - - Environments - summary: Get Environment - description: Returns an environment by its id - operationId: getEnvironment - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Environment' - delete: - tags: - - Environments - summary: DeleteEnvironment - description: Delete environment - operationId: deleteEnvironment - parameters: - - name: programId - in: path - description: Identifier of the application - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: ignoreResourcesDeletionResult - in: query - description: 'Ignore Resources Deletion Result option, delete flow does not fail if resources could not be deleted' - required: false - type: boolean - default: false - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '201': - description: Environment deleted - schema: - $ref: '#/definitions/Environment' - '400': - description: Environment deletion in progress - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Environment not found - '/api/program/{programId}/environment/{environmentId}/regionDeployments/{regionDeploymentId}': - get: - tags: - - Region Deployments - summary: Get Region Deployment - description: Return a region deployment by its id - operationId: getRegionDeployment - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: regionDeploymentId - in: path - description: Identifier of the regionDeployment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of the region deployment for the environment - schema: - $ref: '#/definitions/RegionDeployment' - '/api/program/{programId}/environment/{environmentId}/regionDeployments': - get: - tags: - - Region Deployments - summary: Get Region Deployments - description: List the region deployments for an environment - operationId: getRegionDeployments - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of the region deployments for the environment - schema: - $ref: '#/definitions/RegionDeploymentList' - post: - tags: - - Region Deployments - summary: Create Region Deployment - description: Add region deployments in an environment - operationId: createRegionDeployment - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of an environment - required: true - type: string - - in: body - name: body - description: RegionDeployment - required: true - schema: - type: array - items: - $ref: '#/definitions/NewRegionDeployment' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Region deployment created - schema: - $ref: '#/definitions/RegionDeploymentList' - '400': - description: Bad request - patch: - tags: - - Region Deployments - summary: Patch Region Deployment - description: Remove region deployments from an environment - operationId: patchRegionDeployment - parameters: - - name: programId - in: path - description: Identifier of the application - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - in: body - name: body - description: RegionDeployment - required: true - schema: - type: array - items: - $ref: '#/definitions/RegionDeploymentDeletion' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '202': - description: Region Deployment Modification request accepted - schema: - $ref: '#/definitions/RegionDeploymentList' - '400': - description: Region Deployment Modification bad request - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Region deployment not found for the given identifier - '/api/program/{programId}/environment/{environmentId}/logs': - get: - tags: - - Environments - summary: Get Environment Logs - description: List all logs available in environment - operationId: getEnvironmentLogs - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: service - in: query - description: Names of services - required: true - type: array - items: - type: string - collectionFormat: multi - - name: name - in: query - description: Names of log - required: true - type: array - items: - type: string - collectionFormat: multi - - name: days - in: query - description: number of days for which logs are required - required: true - type: integer - format: int32 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of logs for an environment - schema: - $ref: '#/definitions/EnvironmentLogs' - '400': - description: invalid parameters - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Environment not found - '/api/program/{programId}/environment/{environmentId}/logs/download': - get: - tags: - - Environments - summary: Download Logs - description: Download environment logs - operationId: downloadLogs - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: service - in: query - description: Name of service - required: true - type: string - - name: name - in: query - description: Name of log - required: true - type: string - - name: date - in: query - description: date for which log is required - required: true - type: string - format: date - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Accept - required: false - type: string - description: 'Specify application/json in this header to receive a JSON response. Otherwise, a 307 response code will be returned with a Location header.' - in: header - responses: - '200': - description: Successful retrieval of logs - schema: - $ref: '#/definitions/Redirect' - '400': - description: invalid parameters - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Environment not found - '/api/program/{programId}/environment/{environmentId}/variables': - get: - tags: - - Variables - summary: List User Environment Variables - description: List the user defined variables for an environment (Cloud Service only). - operationId: getEnvironmentVariables - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - x-example: '2351' - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - x-example: '128' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of environment variables - schema: - $ref: '#/definitions/VariableList' - '404': - description: Environment not found - patch: - tags: - - Variables - summary: Patch User Environment Variables - description: 'Modify multiple environment variables (Cloud Service only). To delete a variable, include it with an empty value.' - operationId: patchEnvironmentVariables - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - in: body - name: body - description: 'The list of variables to add, modify, or remove. It is not necessary to send variables here which are not changing. The length of `secretString` values must be less than 500 characters.' - required: true - schema: - type: array - items: - $ref: '#/definitions/EnvironmentVariableUpdate' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '204': - description: Successful setting of variables - '404': - description: Environment not found - '/api/program/{programId}/environment/{environmentId}/reset': - put: - tags: - - Rapid Development Environments - summary: Reset Rapid Development Environment - description: Reset Rapid Development Environment. Also updates the RDE to the latest AEM release. - operationId: resetRde - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '202': - description: Successfully reset RDE - '404': - description: Environment not found - '/api/program/{programId}/environment/{environmentId}/restorePoints': - get: - tags: - - Environment Restore From Backup - summary: Get Restore Points - description: List the backups available for this environment (Cloud Service only) - operationId: getRestorePoints - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of restore points for an environment - schema: - $ref: '#/definitions/RestorePointsList' - '404': - description: Resource not found - '/api/program/{programId}/environment/{environmentId}/restoreExecution/{restoreId}': - get: - tags: - - Environment Restore From Backup - summary: Get Restore Execution - description: Returns a restore execution by its id (Cloud Service only) - operationId: getRestoreExecution - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: restoreId - in: path - description: Identifier of the restore execution - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/RestoreExecution' - '/api/program/{programId}/environment/{environmentId}/restoreExecution/{restoreId}/logs': - get: - tags: - - Environment Restore From Backup - summary: Get Restore Execution Logs - description: Gets the logs of a Restore Execution (Cloud Service only) - operationId: getRestoreExecutionLogs - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: restoreId - in: path - description: Identifier of the restore execution - required: true - type: string - - name: Accept - in: header - required: false - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - default: - description: successful operation - '/api/program/{programId}/environment/{environmentId}/restoreExecutions': - get: - tags: - - Environment Restore From Backup - summary: Lists Restore Executions - description: List the Restore Executions of an environment (Cloud Service only) - operationId: getRestoreExecutions - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: start - in: query - description: Pagination start parameter - required: false - type: string - default: '0' - - name: limit - in: query - description: Pagination limit parameter - required: false - type: integer - default: 5 - format: int32 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/RestoreExecutionList' - '/api/program/{programId}/environment/{environmentId}/restoreExecution': - put: - tags: - - Environment Restore From Backup - summary: Start a Restore Execution - description: Start a Restore from Backup execution (Cloud Service only) - operationId: restoreExecution - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - in: body - name: body - description: Restore Parameters Representation - required: false - schema: - $ref: '#/definitions/RestoreParamRepresentation' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Environment restore in progress - schema: - $ref: '#/definitions/RestoreExecution' - '404': - description: Environment not found - '412': - description: Restore precondition failed - '/api/program/{programId}/pipeline/{pipelineId}/variables': - get: - tags: - - Variables - summary: List User Pipeline Variables - description: List the user defined variables for an pipeline. - operationId: getPipelineVariables - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - x-example: '2351' - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - x-example: '128' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of pipeline variables - schema: - $ref: '#/definitions/VariableList' - '404': - description: Pipeline not found - patch: - tags: - - Variables - summary: Patch User Pipeline Variables - description: 'Modify multiple pipeline variables. To delete a variable, include it with an empty value.' - operationId: patchPipelineVariables - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: pipelineId - in: path - description: Identifier of the pipeline - required: true - type: string - - in: body - name: body - description: 'The list of variables to add, modify, or remove. It is not necessary to send variables here which are not changing. The length of `secretString` values must be less than 500 characters.' - required: true - schema: - type: array - items: - $ref: '#/definitions/PipelineVariableUpdate' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '204': - description: Successful setting of variables - '404': - description: Pipeline not found - '/api/program/{programId}/ipAllowlist/{ipAllowlistId}': - get: - tags: - - IP Allowlist - summary: Get IP Allowlist - description: Returns an IP Allowlist based on program and id - operationId: getIPAllowlist - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of IP Allowlist - schema: - $ref: '#/definitions/IPAllowedList' - '404': - description: Resource not found - put: - tags: - - IP Allowlist - summary: Update IP Allowlist - description: Updates an IP Allowlist for the program with specified values - operationId: updateIPAllowlist - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - in: body - name: body - description: IP Allowlist - required: true - schema: - $ref: '#/definitions/Updateanipallowlist' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: IP Allowlist updated - schema: - $ref: '#/definitions/IPAllowedList' - '400': - description: The request is malformed. - '404': - description: Resource not found - delete: - tags: - - IP Allowlist - summary: Delete IP Allowlist - description: Deletes the IP Allowlist for the program - operationId: deleteIPAllowlist - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '202': - description: Delete was successful - schema: - $ref: '#/definitions/IPAllowedList' - '404': - description: Resource not found - '/api/program/{programId}/ipAllowlist/{ipAllowlistId}/binding/{ipAllowlistBindingId}': - get: - tags: - - IP Allowlist Binding - summary: Get IP Allowlist binding - description: Returns an IP Allowlist binding based on program and IP allowlist id - operationId: getIPAllowlistBinding - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - name: ipAllowlistBindingId - in: path - description: Identifier of the IP Allowlist Binding - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of IP Allowlist - schema: - $ref: '#/definitions/IPAllowedListBinding' - '404': - description: IP Allowlist not found - delete: - tags: - - IP Allowlist Binding - summary: Delete IP Allowlist binding - description: Deletes the IP Allowlist binding for the program and IP Allowlist id - operationId: deleteIPAllowlistBinding - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - name: ipAllowlistBindingId - in: path - description: Identifier of the IP Allowlist binding - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '202': - description: Delete was successful - schema: - $ref: '#/definitions/IPAllowedListBinding' - '404': - description: IP Allowlist not found - '/api/program/{programId}/ipAllowlist/{ipAllowlistId}/bindings': - get: - tags: - - IP Allowlist Binding - summary: Lists IP Allowlist bindings - description: Returns all IP Allowlists bindings for an IpAllowList of a program - operationId: getIPAllowlistBindings - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: The list of IP Allowlists assigned to the program - schema: - $ref: '#/definitions/IPAllowlistBindingsList' - '404': - description: IP Allowlist not found - post: - tags: - - IP Allowlist Binding - summary: Creates an IP Allowlist binding - description: Creates an IP Allowlist binding to an environment for a specific tier - operationId: createIPAllowlistBinding - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: ipAllowlistId - in: path - description: Identifier of the IP Allowlist - required: true - type: string - - in: body - name: body - description: IP Allowlist binding - required: true - schema: - $ref: '#/definitions/IPAllowedListBinding' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/IPAllowedListBinding' - '201': - description: IP Allowlist binding created - schema: - $ref: '#/definitions/IPAllowedListBinding' - '400': - description: The request is malformed. - '404': - description: Environment not found - '412': - description: Creating IP Allowlists for non cloud programs is not supported - '/api/program/{programId}/ipAllowlists': - get: - tags: - - IP Allowlist - summary: Lists IP Allowlists - description: Returns all IP Allowlists that are defined for this program - operationId: getProgramIPAllowlists - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: The list of IP Allowlists assigned to the program - schema: - $ref: '#/definitions/IPAllowlistList' - '404': - description: Program not found - post: - tags: - - IP Allowlist - summary: Creates an IP Allowlist - description: Creates an IP Allowlist for the program with specified values - operationId: createIPAllowlist - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - in: body - name: body - description: IP Allowlist - required: true - schema: - $ref: '#/definitions/Createanewipallowlist' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/IPAllowedList' - '201': - description: IP Allowlist created - schema: - $ref: '#/definitions/IPAllowedList' - '400': - description: The request is malformed. - '404': - description: Program not found - '412': - description: Creating IP Allowlists for non cloud programs is not supported - '/api/program/{programId}/domains': - get: - tags: - - Domain - summary: Get list of domains - description: Gets the list of domains for this program - operationId: getDomain - parameters: - - name: programId - in: path - description: Identifier of program id - required: true - type: string - - name: name - in: query - description: Domain name - required: false - type: string - - name: anyVerified - in: query - description: Filter any verified - required: false - type: boolean - - name: isTxt - in: query - description: Is TXT verified - required: false - type: boolean - - name: isAcme - in: query - description: Is ACME verified - required: false - type: boolean - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: List of domains received - schema: - $ref: '#/definitions/Domain' - post: - tags: - - Domain - summary: Create domain - description: Creates a domain in this program - operationId: createDomain - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: string - - in: body - name: body - description: Payload for creating a domain - required: true - schema: - $ref: '#/definitions/DomainCreate' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Domain' - '201': - description: Domain created - schema: - $ref: '#/definitions/Domain' - '404': - description: Program not found - '409': - description: Domain already exists - '/api/program/{programId}/domain/{domain-id}': - get: - tags: - - Domain - summary: Get domain - description: Gets a domain by its ID - operationId: getDomain - parameters: - - name: programId - in: path - description: Identifier of program id - required: true - type: string - - name: domain-id - in: path - description: Identifier of domain id - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Domain received - schema: - $ref: '#/definitions/Domain' - '404': - description: Domain not found - put: - tags: - - Domain - summary: Update domain - description: Updates a domain with specified values - operationId: modifyDomain - parameters: - - name: programId - in: path - description: Identifier of program id - required: true - type: string - - name: domain-id - in: path - description: Identifier of domain id - required: true - type: string - - in: body - name: body - description: Domain Update Body - required: true - schema: - $ref: '#/definitions/UpdateaDomain''snameorlabel' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Domain updated - schema: - $ref: '#/definitions/Domain' - '404': - description: Program not found - delete: - tags: - - Domain - summary: Delete domain - description: Delete a domain from this program - operationId: deleteDomain - parameters: - - name: programId - in: path - description: Identifier of program id - required: true - type: string - - name: domain-id - in: path - description: Identifier of domain id - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Domain deleted - schema: - $ref: '#/definitions/Domain' - '/api/program/{programId}/domain/{domain-id}/validate': - put: - tags: - - Domain - summary: Check validation - description: Validate the domain based on the type of validation token - operationId: domainValidationToken - parameters: - - name: programId - in: path - description: Identifier of program id - required: true - type: string - - name: domain-id - in: path - description: Identifier of domain id - required: true - type: string - - in: body - name: body - description: Payload for validation operation - required: true - schema: - $ref: '#/definitions/DomainTokenValidationBody' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Validation is completed - schema: - $ref: '#/definitions/Domain' - '404': - description: Program not found - '/api/program/{programId}/domain/{domain-id}/validation': - post: - tags: - - Domain - summary: Creates validation token - description: Creates a validation token in order to establish the ownership of the domain - operationId: domainValidationToken - parameters: - - name: programId - in: path - description: Identifier of program id - required: true - type: string - - name: domain-id - in: path - description: Identifier of domain id - required: true - type: string - - in: body - name: body - description: Payload for validation operation - required: true - schema: - $ref: '#/definitions/DomainTokenValidationBody' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Created validation token - schema: - $ref: '#/definitions/Domain' - '404': - description: Program Not found - '/api/program/{programId}/domain-mapping/{domainMappingId}': - get: - tags: - - Domain Mappings - CDN Configurations - summary: Get domain mapping - description: Gets a domain mapping by its ID - operationId: getDomainMappingById - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: domainMappingId - in: path - description: Identifier of domain mapping - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Domain Mapping retrieved - schema: - $ref: '#/definitions/DomainMapping' - '404': - description: Domain Mapping not found - put: - tags: - - Domain Mappings - CDN Configurations - summary: Update domain mapping - description: Updates a domain mapping with the specified values - operationId: updateDomainMapping - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: domainMappingId - in: path - description: Identifier of domain mapping - required: true - type: integer - format: int64 - - in: body - name: body - description: Payload for updating a domain mapping - required: true - schema: - $ref: '#/definitions/Updateadomainmapping' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Domain Mapping updated - schema: - $ref: '#/definitions/DomainMapping' - '404': - description: Domain Mapping not found - delete: - tags: - - Domain Mappings - CDN Configurations - summary: Delete domain mapping - description: Deletes a domain mapping - operationId: deleteDomainMapping - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: domainMappingId - in: path - description: Identifier of domain mapping - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Domain Mapping deleted - schema: - $ref: '#/definitions/DomainMapping' - '404': - description: Domain Mapping not found - '/api/program/{programId}/domain-mapping/{domainMappingId}/verify': - put: - tags: - - Domain Mappings - CDN Configurations - summary: Check if customer made the required DNS changes - description: Check if customer made the required DNS changes in order to route traffic from the domain - operationId: validateHelixDomain - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: domainMappingId - in: path - description: Identifier of domain mapping - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: DNS changes were successfully made - schema: - $ref: '#/definitions/DomainMapping' - '404': - description: Program not found - '/api/program/{programId}/domain-mappings': - get: - tags: - - Domain Mappings - CDN Configurations - summary: List of domain mappings - description: Gets the list of domain mappings from this program. - operationId: getAllDomainMappingsByProgramId - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: originId - in: query - description: Filtering by origin ID - required: false - type: integer - format: int64 - - name: certificateId - in: query - description: Filtering by certificateId - required: false - type: integer - format: int64 - - name: domainId - in: query - description: Filtering by domainId - required: false - type: integer - format: int64 - - name: status - in: query - description: Filtering by status separated by comma - required: false - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: List of domain mappings retrieved - schema: - $ref: '#/definitions/DomainMappingList' - post: - tags: - - Domain Mappings - CDN Configurations - summary: Create domain mapping - description: Creates a domain mapping (CDN configuration) in this program - operationId: createDomainMapping - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - in: body - name: body - description: Payload for creating a domain mapping - required: true - schema: - $ref: '#/definitions/Createanewdomainmapping' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/DomainMapping' - '201': - description: Domain Mapping created - schema: - $ref: '#/definitions/DomainMapping' - '/api/program/{programId}/environment/{environmentId}/domain-mappings': - get: - tags: - - Domain Mappings - CDN Configurations - summary: List of domain mappings by environment - description: Gets the list of domain mappings for the specified environment ID. - operationId: getAllDomainMappingsByProgramIdAndEnvironmentId - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: environmentId - in: path - description: Identifier of environment - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: List of domain mappings by environment retrieved - schema: - $ref: '#/definitions/DomainMappingList' - '/api/program/{programId}/site/{siteId}/domain-mappings': - get: - tags: - - Domain Mappings - CDN Configurations - summary: List of domain mappings by EDS site - description: Get the list of domain mappings for the specified EDS site ID. - operationId: getAllDomainMappingsByProgramIdAndSiteId - parameters: - - name: programId - in: path - description: Identifier of program - required: true - type: integer - format: int64 - - name: siteId - in: path - description: Identifier of EDS site - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: List of domain mappings by environment retrieved - schema: - $ref: '#/definitions/DomainMappingList' - '/api/program/{programId}/certificate/{certificateId}': - get: - tags: - - SSL Certificates - summary: Get certificate - description: Gets a certificate by its ID - operationId: getCertificateByIdAndProgramId - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: integer - format: int64 - - name: certificateId - in: path - description: Identifier of the certificate - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Certificate retrieved - schema: - $ref: '#/definitions/SslCertificateRepresentation' - '404': - description: Certificate not found - schema: - $ref: '#/definitions/SslCertificateNotFoundException' - put: - tags: - - SSL Certificates - summary: Update certificate - description: Updates a certificate in this program - operationId: updateCertificate - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: integer - format: int64 - - name: certificateId - in: path - description: Identifier of the certificate - required: true - type: integer - format: int64 - - in: body - name: body - description: Payload for updating the certificate - required: true - schema: - $ref: '#/definitions/CreateOrUpdateSslCertificateBody' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Certificate updated - schema: - $ref: '#/definitions/SslCertificateRepresentation' - '404': - description: Certificate not found - schema: - $ref: '#/definitions/SslCertificateNotFoundException' - delete: - tags: - - SSL Certificates - summary: Delete certificate - description: Deletes a certificate from this program - operationId: deleteCertificate - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: integer - format: int64 - - name: certificateId - in: path - description: Identifier of the certificate - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Certificate deleted - schema: - $ref: '#/definitions/SslCertificateRepresentation' - '404': - description: Certificate not found - schema: - $ref: '#/definitions/SslCertificateNotFoundException' - '/api/program/{programId}/certificates': - get: - tags: - - SSL Certificates - summary: Get all certificates - description: Gets the list of certificates from this program - operationId: getAllCertificatesForProgram - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: integer - format: int64 - - name: start - in: query - description: Pagination start parameter - required: false - type: string - default: '0' - - name: limit - in: query - description: Pagination limit parameter - required: false - type: integer - default: 20 - format: int32 - - name: status - in: query - description: Filter statuses separated by comma - required: false - type: string - enum: - - VALID - - PENDING - - EXPIRED - - name: name - in: query - description: Certificate name - required: false - type: string - - name: sslCertificateType - in: query - description: Certificate types separated by comma. - required: false - type: string - enum: - - DV - - EV - - OV - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Certificate list retrieved - schema: - $ref: '#/definitions/AllSSLCertificatesList' - post: - tags: - - SSL Certificates - summary: Add SSL certificate - description: Adds a customer-managed certificate in this program - operationId: createSslCertificate - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: integer - format: int64 - - in: body - name: body - description: Payload for creating the certificate - required: true - schema: - $ref: '#/definitions/CreateOrUpdateSslCertificateBody' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/SslCertificateRepresentation' - '201': - description: SSL certificate created - schema: - $ref: '#/definitions/SslCertificateRepresentation' - '/api/program/{programId}/dv-certificates': - post: - tags: - - SSL Certificates - summary: Create DV certificate - description: Initiates the creation of a DV certificate in this program - operationId: createDvCertificate - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: integer - format: int64 - - in: body - name: body - description: Payload for creating the DV certificate - required: true - schema: - $ref: '#/definitions/CreateDvCertificateBody' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/SslCertificate' - '201': - description: Created DV certificate - schema: - $ref: '#/definitions/SslCertificate' - '/api/program/{programId}/site/{siteId}': - get: - tags: - - EDS Sites - summary: Get Site by Id - description: '' - operationId: retrieveSite - parameters: - - name: programId - in: path - required: true - type: string - - name: siteId - in: path - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Site retrieved - schema: - $ref: '#/definitions/Site' - '404': - description: Site could not be found - put: - tags: - - EDS Sites - summary: Update Site - description: '' - operationId: updateSite - parameters: - - name: programId - in: path - required: true - type: string - - name: siteId - in: path - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Site updated - schema: - $ref: '#/definitions/Site' - '404': - description: Site could not be found - delete: - tags: - - EDS Sites - summary: Delete Site - description: '' - operationId: deleteSite - parameters: - - name: programId - in: path - required: true - type: string - - name: siteId - in: path - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Site deleted - schema: - $ref: '#/definitions/Site' - '404': - description: Site could not be found - '/api/program/{programId}/site/{siteId}/validate': - put: - tags: - - EDS Sites - summary: Validate Site - description: '' - operationId: validateSite - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: siteId - in: path - description: Identifier of the site - required: true - type: integer - format: int64 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Site validated - schema: - $ref: '#/definitions/Site' - '400': - description: Site could not be validated. CloudManager challenge does not match - '500': - description: Internal Server Error - '504': - description: Site could not be validated in time - '/api/program/{programId}/sites': - get: - tags: - - EDS Sites - summary: Get All Sites by programId - description: '' - operationId: getProgramSites - parameters: - - name: programId - in: path - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Sites retrieved - schema: - $ref: '#/definitions/SiteList' - post: - tags: - - EDS Sites - summary: Create Site - description: '' - operationId: createSite - parameters: - - name: programId - in: path - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/Site' - '201': - description: Site created - schema: - $ref: '#/definitions/Site' - '/api/program/{programId}/feedbacks': - post: - tags: - - Programs - summary: Post feedback - description: Add new feedback - operationId: postFeedback - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - in: body - name: body - description: Feedback - required: true - schema: - $ref: '#/definitions/NewFeedback' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '400': - description: Invalid request - '404': - description: Application not found - '/api/program/{programId}/newRelicUsers': - get: - tags: - - Programs - summary: Get New Relic Sub Account users list - description: Get New Relic Sub Account users list for this program - operationId: getNewRelicSubAccountUserList - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of the list of New Relic Sub Account users - schema: - $ref: '#/definitions/NewRelicSubAccountUserlist' - '400': - description: The request is malformed. - '401': - description: The request has not been applied because it lacks valid authentication credentials for the target resource. - '403': - description: The requester is not authorized to access the resource. - '405': - description: Client sent a request using a HTTP method that the server doesn't support. - '406': - description: Unacceptable content type. Client sent an Accept header for a content type which does not exist on the server. - '422': - description: Unprocessable Entity - '500': - description: This is an indicator of a server-side error. - '502': - description: This is an indicator that the back-end service did not send a valid response. - '503': - description: This is an indicator of a potential server overload. - '504': - description: This is an indicator that the back-end service did not complete a response within an allowed time period. - patch: - tags: - - Programs - summary: Create and Delete New Relic Sub Account users - description: Create and Delete New Relic Sub Account users for this program - operationId: createDeleteNewRelicSubAccountUsers - parameters: - - in: body - name: body - description: New Relic Sub-Account Users - required: true - schema: - $ref: '#/definitions/NewRelicSubAccountUser' - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/NewRelicSubAccountUserlist' - '204': - description: Successful New Relic Sub Account user flow initiation - '400': - description: The request is malformed. - '401': - description: The request has not been applied because it lacks valid authentication credentials for the target resource. - '403': - description: The requester is not authorized to access the resource. - '404': - description: Program not found - '406': - description: Unacceptable content type. Client sent an Accept header for a content type which does not exist on the server. - '500': - description: This is an indicator of a server-side error. - '502': - description: This is an indicator that the back-end service did not send a valid response. - '503': - description: This is an indicator of a potential server overload. - '504': - description: This is an indicator that the back-end service did not complete a response within an allowed time period. - /api/tenants: - get: - tags: - - Tenants - summary: List Tenants - description: Lists all tenants - operationId: getTenants - parameters: - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of tenant list - schema: - $ref: '#/definitions/TenantList' - '/api/tenant/{tenantId}': - get: - tags: - - Tenants - summary: Get Tenant - description: Returns a tenant by its id - operationId: getTenant - parameters: - - name: tenantId - in: path - description: Identifier of the tenant - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of tenant - schema: - $ref: '#/definitions/Tenant' - '404': - description: Tenant not found - '/api/tenant/{tenantId}/programs': - get: - tags: - - Programs - summary: Lists Programs for Tenant - description: Returns all programs defined for tenant. - operationId: getProgramsForTenant - parameters: - - name: tenantId - in: path - description: Identifier of the tenant - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/ProgramList' - '404': - description: Tenant not found. - post: - tags: - - Programs - summary: Create Program - description: Creates a program - operationId: addProgram - parameters: - - name: tenantId - in: path - description: Identifier of the tenant - required: true - type: string - - in: body - name: body - description: Program - required: true - schema: - $ref: '#/definitions/NewProgram' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Creation was successful. - schema: - $ref: '#/definitions/Program' - '409': - description: Program already exists. - '/api/program/{programId}/regions': - get: - tags: - - Regions - summary: Lists Regions - description: Returns all Regions that can be used to create environments for this program. - operationId: getProgramRegions - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/RegionsList' - '/api/program/{programId}/networkInfrastructures': - get: - tags: - - Network infrastructure - summary: List Network Infrastructures - description: Lists all network infrastructures in an program - operationId: getNetworkInfrastructures - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of network infrastructure list - schema: - $ref: '#/definitions/NetworkInfrastructuresList' - '404': - description: Program not found - post: - tags: - - Network infrastructure - summary: Create network configuration - description: Create a new network configuration - operationId: createNetworkInfrastructure - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - in: body - name: body - description: Configuration - required: true - schema: - $ref: '#/definitions/NetworkInfrastructure' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Network infrastructure created - schema: - $ref: '#/definitions/NetworkInfrastructure' - '404': - description: Resource not found - '/api/program/{programId}/networkInfrastructure/{networkInfrastructureId}': - get: - tags: - - Network infrastructure - summary: Get network infrastructure - description: Gets an existing network infrastructure - operationId: getNetworkInfrastructure - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: networkInfrastructureId - in: path - description: Identifier of the network infrastructure - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Got network Infrastructure details - schema: - $ref: '#/definitions/NetworkInfrastructure' - '404': - description: Network Infrastructure not found - put: - tags: - - Network infrastructure - summary: Update network infrastructure - description: Updates an existing network infrastructure - operationId: updateNetworkInfrastructure - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: networkInfrastructureId - in: path - description: Identifier of the network infrastructure - required: true - type: string - - in: body - name: body - description: Configuration - required: true - schema: - $ref: '#/definitions/NetworkInfrastructure' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Network infrastructure updated - schema: - $ref: '#/definitions/NetworkInfrastructure' - '404': - description: Network Infrastructure not found - delete: - tags: - - Network infrastructure - summary: Delete network infrastructure - description: Deletes an existing network infrastructure - operationId: deleteNetworkInfrastructure - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: networkInfrastructureId - in: path - description: Identifier of the network infrastructure - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: successful operation - schema: - $ref: '#/definitions/NetworkInfrastructure' - '204': - description: Network infrastructure deleted - schema: - $ref: '#/definitions/NetworkInfrastructure' - '400': - description: Network Infrastructure cannot be deleted - '404': - description: Network Infrastructure not found - '/api/program/{programId}/environment/{environmentId}/advancedNetworking': - get: - tags: - - Environment Advanced Networking Configuration - summary: Get Environment Advanced Networking Configurations - description: Returns environment advanced networking configurations by its id - operationId: getEnvironmentAdvancedNetworkingConfigurationList - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Environment Advanced Networking Configurations - schema: - $ref: '#/definitions/AdvancedNetworkingConfigurationList' - '404': - description: Resource not found - put: - tags: - - Environment Advanced Networking Configuration - summary: Enable Environment Advanced Networking Configuration - description: Enable an environment advanced networking configuration by its id - operationId: enableEnvironmentAdvancedNetworkingConfiguration - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - in: body - name: body - description: ' Environment Advanced Networking Configuration' - required: true - schema: - $ref: '#/definitions/EnableAdvancedNetworkingConfiguration' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Environment Advanced Networking Configuration started - schema: - $ref: '#/definitions/Environment' - '400': - description: Validation exception - '404': - description: Resource not found - delete: - tags: - - Environment Advanced Networking Configuration - summary: Disable Environment Advanced Networking Configuration - description: Disable an environment advanced networking configuration by its id - operationId: disableEnvironmentAdvancedNetworkingConfiguration - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the environment - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Environment Advanced Networking Configuration disabled - schema: - $ref: '#/definitions/Environment' - '400': - description: Validation exception - '404': - description: Resource not found - '/api/program/{programId}/contentSets': - get: - tags: - - ContentSets - summary: Lists Content Sets for program - description: Returns all content sets defined for the program. - operationId: getContentSets - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: List content sets - schema: - $ref: '#/definitions/ContentSetList' - '400': - description: Bad request - post: - tags: - - ContentSets - summary: Create content set - description: create a content set - operationId: createContentSet - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - in: body - name: body - description: Content set - required: true - schema: - $ref: '#/definitions/NewContentSet' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Content Set created - schema: - $ref: '#/definitions/ContentSet' - '400': - description: Bad request - '404': - description: Program not found - '/api/program/{programId}/contentSet/{contentSetId}': - get: - tags: - - ContentSets - summary: Get content set - description: Gets a content set by Id - operationId: getContentSet - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentSetId - in: path - description: Identifier of the content set - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Found content set - schema: - $ref: '#/definitions/ContentSet' - '400': - description: Bad request - '404': - description: Content set not found - put: - tags: - - ContentSets - summary: Update content set - description: Updates the content set - operationId: updateContentSet - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentSetId - in: path - description: Identifier of the content set - required: true - type: string - - in: body - name: body - description: Content set - required: true - schema: - $ref: '#/definitions/ContentSet' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Content set updated - schema: - $ref: '#/definitions/ContentSet' - '400': - description: Bad request - '404': - description: Content set not found - delete: - tags: - - ContentSets - summary: Delete content set - description: Deletes the content set by Id - operationId: deleteContentSet - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentSetId - in: path - description: Identifier of the content set - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Content set deleted - schema: - $ref: '#/definitions/ContentSet' - '400': - description: Bad request - '404': - description: Content set not found - '/api/program/{programId}/contentFlows': - get: - tags: - - ContentSets - summary: List content flows for the program - description: List all content flows for a program - operationId: listContentFlows - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: start - in: query - description: Pagination start parameter - required: false - type: string - default: '0' - - name: limit - in: query - description: Pagination limit parameter - required: false - type: integer - default: 20 - format: int32 - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: List content flows - schema: - $ref: '#/definitions/ContentFlowList' - '400': - description: Bad request - '/api/program/{programId}/environment/{environmentId}/contentFlow': - post: - tags: - - ContentSets - summary: Execute content flow using content set - description: Executes a content flow - operationId: createContentFlow - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: environmentId - in: path - description: Identifier of the source environment - required: true - type: string - - in: body - name: body - description: Content Flow details - required: true - schema: - $ref: '#/definitions/ContentFlowInput' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '201': - description: Content Flow started - schema: - $ref: '#/definitions/ContentFlow' - '400': - description: Bad request - '403': - description: The requester is not authorized to access the resource. - '404': - description: Program not found - '/api/program/{programId}/contentFlow/checkCompatibility': - post: - tags: - - ContentSets - summary: Backflow Compatibility between source and target environments - description: Returns the compatibility between source and target environments - operationId: checkBackflowCompatibility - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - in: body - name: body - description: Program - required: true - schema: - $ref: '#/definitions/CompatibilityCheckInput' - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - - name: Content-Type - in: header - description: Must always be application/json - required: true - type: string - responses: - '200': - description: Big Bear Topology Compatibility Response - schema: - $ref: '#/definitions/CompatibilityCheckResponse' - '400': - description: Bad request - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Program not found - '/api/program/{programId}/contentFlow/{contentFlowId}': - get: - tags: - - ContentSets - summary: Get content flow - description: Gets content flow for a program - operationId: getContentFlow - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentFlowId - in: path - description: Identifier of the contentFlow - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of the content flow - schema: - $ref: '#/definitions/ContentFlow' - '400': - description: Bad request - delete: - tags: - - ContentSets - summary: Cancel content flow (Cloud Service only). - description: Cancel content flow - operationId: cancelContentFlow - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentFlowId - in: path - description: Identifier of the content flow - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Content flow canceled - schema: - $ref: '#/definitions/ContentFlow' - '400': - description: Bad request - '/api/program/{programId}/contentFlow/{contentFlowId}/logs': - get: - tags: - - ContentSets - summary: Get Content Flow Logs - description: Get Content Flow Logs - operationId: getContentFlowLogs - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentFlowId - in: path - description: Identifier of the content flow - required: true - type: string - - name: jobType - in: query - description: 'Job type (import, export)' - required: true - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of logs - schema: - $ref: '#/definitions/ContentFlowLogs' - '400': - description: Missing JobType - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Program not found. - '/api/program/{programId}/contentFlow/{contentFlowId}/logs/download': - get: - tags: - - ContentSets - summary: Download content flow logs - description: Download content flow logs - operationId: downloadLogs - parameters: - - name: programId - in: path - description: Identifier of the program - required: true - type: string - - name: contentFlowId - in: path - description: Identifier of the content flow - required: true - type: string - - name: jobType - in: query - description: 'Job type (import, export)' - required: true - type: string - - name: Accept - in: header - required: false - type: string - - name: x-gw-ims-org-id - in: header - description: IMS organization ID that the request is being made under. - required: true - type: string - - name: Authorization - in: header - description: 'Bearer [token] - An access token for the technical account created through integration with Adobe IO' - required: true - type: string - - name: x-api-key - in: header - description: IMS Client ID (API Key) which is subscribed to consume services on console.adobe.io - required: true - type: string - responses: - '200': - description: Successful retrieval of logs - excludeSchema: true - schema: - $ref: '#/definitions/Redirect' - '400': - description: Missing JobType - schema: - $ref: '#/definitions/BadRequestError' - '404': - description: Program not found. -definitions: - ProgramList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - programs: - type: array - items: - $ref: '#/definitions/EmbeddedProgram' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - EmbeddedProgram: - type: object - properties: - id: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - readOnly: true - name: - type: string - example: AcmeCorp Main Site - description: Name of the program - readOnly: true - enabled: - type: boolean - description: Whether this Program has been enabled for Cloud Manager usage - default: false - readOnly: true - tenantId: - type: string - example: acmeCorp - description: Tenant Id - readOnly: true - status: - type: string - description: Status of the program - enum: - - creating - - ready - - deleting - - deleted - - deleted_failed - - failed - createdAt: - type: string - format: date-time - description: Created time - updatedAt: - type: string - format: date-time - description: Date of last change - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/tenant': - description: The tenant this program belongs to - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A lightweight representation of a Program - Program: - type: object - required: - - name - - type - properties: - id: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - name: - type: string - example: AcmeCorp Main Site - description: Name of the program - minLength: 0 - maxLength: 64 - pattern: '(?=.*[a-zA-Z])[-+!''"/#$%&*.,;:()’@-}À-ÿ– 0-9]*' - enabled: - type: boolean - description: Whether this Program has been enabled for Cloud Manager usage - default: false - tenantId: - type: string - example: acmeCorp - description: Tenant Id - imsOrgId: - type: string - example: 6522A55453334E247F120101@AdobeOrg - description: Organisation Id - status: - type: string - description: Status of the program - enum: - - creating - - ready - - deleting - - deleted - - deleted_failed - - failed - type: - type: string - example: aem_cloud_service - description: The type of program - enum: - - aem_managed_services - - aem_cloud_service - - media_library - capabilities: - example: '{ ''capability1'':''value1'', ''capability1'': {''param3'':''value3''}}' - description: Program capabilities - $ref: '#/definitions/ProgramCapabilities' - createdAt: - type: string - format: date-time - description: Created time - updatedAt: - type: string - format: date-time - description: Date of last change - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/pipelines': - description: Pipelines defined in the program - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/environments': - description: The environments linked to this program. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/repositories': - description: The repositories linked to this program. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/ipAllowlists': - description: The IP allowlists linked to this program. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/certificates': - description: The SSL certificates linked to this program. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/tenant': - description: The tenant this program belongs to - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/networkInfrastructures': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/regions': - description: The regions available for this program. - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A representation of a Program - ProgramCapabilities: - type: object - properties: - sandbox: - type: boolean - example: true - description: Indicator of a sandbox program. - readOnly: true - default: false - description: Contains the program capabilities - HalLink: - type: object - properties: - href: - type: string - templated: - type: boolean - default: false - type: - type: string - deprecation: - type: string - profile: - type: string - title: - type: string - hreflang: - type: string - name: - type: string - Pipeline: - type: object - required: - - name - - phases - properties: - id: - type: string - example: '29' - description: Identifier of the pipeline. Unique within the program. - programId: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - name: - type: string - example: AcmeCorp Main Pipeline - description: Name of the pipeline - minLength: 1 - maxLength: 64 - trigger: - type: string - example: MANUAL - description: 'How should the execution be triggered. ON_COMMIT: each time one or more commits are pushed and the Pipeline is idle then a execution is triggered. MANUAL: triggerd through UI or API.' - enum: - - ON_COMMIT - - MANUAL - status: - type: string - example: IDLE - description: Pipeline status - enum: - - IDLE - - BUSY - - WAITING - createdAt: - type: string - format: date-time - description: Create date - readOnly: true - updatedAt: - type: string - format: date-time - description: Update date - readOnly: true - lastStartedAt: - type: string - format: date-time - description: Last pipeline execution start - readOnly: true - lastFinishedAt: - type: string - format: date-time - description: Last pipeline execution end - readOnly: true - phases: - type: array - description: Pipeline phases in execution order - items: - $ref: '#/definitions/PipelinePhase' - maxItems: 100 - minItems: 1 - type: - type: string - example: CI_CD - description: Pipeline type - enum: - - CI_CD - - CODE_GENERATOR - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Program this pipeline belongs to. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/execution': - description: Current pipeline execution if any - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/execution/id': - description: Get pipeline execution by id - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/executions': - description: Get all historic executions for this pipeline. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/variables': - description: Custom pipeline variables - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/rollbackLastSuccessfulExecution': - description: Start a CI/CD rollback execution - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/cache': - description: Pipeline cache - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A representation of a CI/CD Pipeline - PipelinePhase: - type: object - required: - - type - properties: - name: - type: string - example: DEV Build - description: Name of the phase - type: - type: string - example: DEPLOY - description: Type of the phase - enum: - - VALIDATE - - BUILD - - DEPLOY - repositoryId: - type: string - description: |- - Identifier of the source repository. The code from this repository will be build at the start of this phase. - Mandatory if type=BUILD - branch: - type: string - description: |- - Name of the tracked branch or a fully qualified git tag (e.g. refs/tags/v1). - Assumed to be `master` if missing. - environmentId: - type: string - description: Identifier of the target environment. Mandatory if type=DEPLOY - environmentType: - type: string - description: 'Type of environment (for example stage or prod, readOnly = true)' - enum: - - dev - - stage - - prod - - rde - - preprod - steps: - type: array - description: 'Steps to be included in the phase in execution order. Might be added or not, depending on permissions or configuration' - items: - $ref: '#/definitions/PipelineStep' - description: Describes a phase of a pipeline - PipelineList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - pipelines: - type: array - items: - $ref: '#/definitions/Pipeline' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - PipelineExecution: - type: object - properties: - id: - type: string - description: Pipeline execution identifier - programId: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - readOnly: true - pipelineId: - type: string - example: '10' - description: Identifier of the pipeline. Unique within the space. - readOnly: true - artifactsVersion: - type: string - description: Version of the artifacts generated during this execution - user: - type: string - example: 0123456789ABCDE@AdobeID - description: AdobeID who started the pipeline. Empty for auto triggered builds - status: - type: string - description: Status of the execution - enum: - - NOT_STARTED - - RUNNING - - CANCELLING - - CANCELLED - - FINISHED - - ERROR - - FAILED - trigger: - type: string - description: How the execution was triggered. - enum: - - ON_COMMIT - - MANUAL - - PUSH_UPGRADES - pipelineExecutionMode: - type: string - description: The mode in which the execution occurred. EMERGENCY mode will skip certain steps and is only available to select AMS customers - enum: - - NORMAL - - EMERGENCY - createdAt: - type: string - format: date-time - description: Timestamp at which the execution was created - updatedAt: - type: string - format: date-time - description: Timestamp at which the status of the execution last changed - finishedAt: - type: string - format: date-time - description: Timestamp at which the execution completed - pipelineType: - type: string - example: CI_CD - description: Pipeline type - enum: - - CI_CD - - CODE_GENERATOR - _embedded: - type: object - readOnly: true - properties: - stepStates: - type: array - items: - $ref: '#/definitions/PipelineExecutionStepState' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: Get the program of the execution - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline': - description: Get the pipeline of the execution - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A representation of an execution of a CI/CD Pipeline. - PipelineExecutionStepState: - type: object - properties: - id: - type: string - stepId: - type: string - phaseId: - type: string - action: - type: string - example: build - description: Name of the action - repository: - type: string - description: Target repository - branch: - type: string - description: Target branch - environment: - type: string - description: Target environment - environmentId: - type: string - description: Target environment id - environmentType: - type: string - description: Target environment type - startedAt: - type: string - format: date-time - description: Timestamp at which the step state started running - finishedAt: - type: string - format: date-time - description: Timestamp at which the step completed - commitId: - type: string - description: Target commit id - details: - type: object - description: Additional details of the step - $ref: '#/definitions/PipelineExecutionStepStateDetails' - status: - type: string - example: NOT_STARTED - description: Action status - enum: - - NOT_STARTED - - RUNNING - - FINISHED - - ERROR - - ROLLING_BACK - - ROLLED_BACK - - WAITING - - CANCELLED - - FAILED - - INCOMPLETE - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/execution': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline': - description: Get the pipeline of the execution - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline/logs': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline/metrics': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline/reExecute': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline/advance': - description: 'Post to this link in order to advance the pipeline, if paused and waiting for user interaction. Link is present in output only in that case.' - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline/cancel': - description: Post to this link in order to cancel the pipeline. Link is present in output only in that case. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/program': - description: Get the program of the execution - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes the status of a particular pipeline execution step for display purposes - PipelineExecutionListRepresentation: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - executions: - type: array - items: - $ref: '#/definitions/PipelineExecution' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: List of pipeline executions - PipelineStepMetrics: - type: object - properties: - metrics: - type: array - description: metrics - readOnly: true - items: - $ref: '#/definitions/Metric' - Metric: - type: object - properties: - id: - type: string - description: KPI result identifier - severity: - type: string - description: Severity of the metric - enum: - - critical - - important - - informational - passed: - type: boolean - description: Whether metric is considered passed - default: false - override: - type: boolean - description: Whether user override the failed metric - default: false - actualValue: - type: string - description: Expected value for the metric - expectedValue: - type: string - description: Expected value for the metric - comparator: - type: string - description: Comparator used for the metric - enum: - - GT - - GTE - - LT - - LTE - - EQ - - NEQ - kpi: - type: string - description: KPI identifier - description: A representation of a specific metric generated by a CI/CD Pipeline step. - EnvironmentList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - environments: - type: array - items: - $ref: '#/definitions/Environment' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - Environment: - type: object - properties: - id: - type: string - description: id - programId: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - name: - type: string - example: AcmeCorp Dev1 Environment - description: Name of the environment - pattern: '(?=.*[a-zA-Z])[-+!''"/#$%&*.,;()@-} 0-9]*' - description: - type: string - example: This is our primary development environment - description: Description of the environment - type: - type: string - example: dev - description: Type of the environment - enum: - - dev - - stage - - prod - - rde - - preprod - status: - type: string - example: creating - description: Status of the environment - enum: - - creating - - ready - - deleting - - deleted - - updating - - failed - - deploy_failed - - created - - restoring - - restore_failed - - resetting - - reset_failed - - degraded - - hibernated - region: - type: string - example: va7 - description: Region of the environment - availableLogOptions: - type: array - description: List of logs available in the environment - items: - $ref: '#/definitions/LogOptionRepresentation' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Program this environment belongs to. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline': - description: 'The Pipeline this environment is assigned to, if any' - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/author': - description: Author URL - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/publish': - description: Publish URL - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/preview': - description: Publish URL - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/developerConsole': - description: Developer Console URL - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/logs': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/variables': - description: Custom environment variables - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/advancedNetworking': - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A representation of an Environment known to Cloud Manager. - Repository: - type: object - properties: - repo: - type: string - example: Adobe-Marketing-Cloud - description: Repository name. Once set it cannot be updated - description: - type: string - example: Description - description: description - repositoryUrl: - type: string - example: 'https://git.cloudmanager.adobe.com/weretailprod/we-retail-global' - description: Repository Url. - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Program the repository belongs to - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/branches': - description: List of branches in this repository - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A sourcecode repository - RepositoryList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - repositories: - type: array - items: - $ref: '#/definitions/Repository' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - RepositoryBranch: - type: object - properties: - programId: - type: string - example: '14' - description: Identifier of the program. Unique within the space - repositoryId: - type: integer - format: int64 - example: 2 - description: Identifier of the repository - name: - type: string - example: master - description: Name of the branch - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: Program - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/repository': - description: Repository - $ref: '#/definitions/HalLink' - description: Represents a Git Branch - BranchList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - branches: - type: array - items: - $ref: '#/definitions/RepositoryBranch' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - RequestedPageDetails: - type: object - properties: - start: - type: integer - format: int32 - description: The start index for the current page of results - limit: - type: integer - format: int32 - description: The item limit for the current page of results - next: - type: integer - format: int32 - description: The start index for the next page of results - prev: - type: integer - format: int32 - description: The start index for the previous page of results - orderBy: - type: string - property: - type: array - items: - type: string - type: - type: string - description: Filtering and sorting page details - MissingParameter: - type: object - properties: - name: - type: string - example: paramName - description: Name of the missing parameter. - type: - type: string - example: string - description: Type of the missing parameter. - InvalidParameter: - type: object - properties: - name: - type: string - example: paramName - description: Name of the invalid parameter. - reason: - type: string - example: value must be a positive number - description: Reason of why the parameter's value is not accepted. - BadRequestError: - type: object - properties: - status: - type: integer - format: int32 - example: 4xx - description: HTTP status code of the response. - type: - type: string - example: 'http://ns.adobe.com/adobecloud/error' - description: Error type identifier. - title: - type: string - example: Validation failed - description: A short summary of the error. - missingParams: - type: array - description: Request's missing parameters. - items: - $ref: '#/definitions/MissingParameter' - invalidParams: - type: array - description: Request's invalid parameters. - items: - $ref: '#/definitions/InvalidParameter' - description: A Bad Request response error. - EnvironmentLog: - type: object - properties: - service: - type: string - example: author - description: Name of the service - name: - type: string - example: aemerror - description: Name of the Log - date: - type: string - example: '2019-04-05' - description: date of the Log - format: date - programId: - type: integer - format: int64 - environmentId: - type: integer - format: int64 - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/logs/download': - description: Download Logs link - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/logs/tail': - description: Tail Log link - $ref: '#/definitions/HalLink' - description: Log from Environment - EnvironmentLogs: - type: object - properties: - service: - type: array - example: author - description: Name of the service - items: - type: string - name: - type: array - example: aemerror - description: Name of the Log - items: - type: string - days: - type: integer - format: int32 - example: 2 - description: Number of days - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Application this environment belongs to. - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - _embedded: - type: object - readOnly: true - properties: - downloads: - type: array - description: Links to logs - items: - $ref: '#/definitions/EnvironmentLog' - description: Logs of an Environment - Variable: - type: object - properties: - name: - type: string - example: MY_VAR1 - description: 'Name of the variable. Can only consist of a-z, A-Z, _ and 0-9 and cannot begin with a number.' - minLength: 2 - maxLength: 100 - pattern: '[a-zA-Z_][a-zA-Z_0-9]*' - value: - type: string - example: myValue - description: 'Value of the variable. Read-Write for non-secrets, write-only for secrets. The length of `secretString` values must be less than 500 characters. An empty value causes a variable to be deleted.' - minLength: 0 - maxLength: 2048 - type: - type: string - example: string - description: Type of the variable. Default `string` if missing. `secretString` variables are encrypted at rest. The type of a variable be changed after creation; the variable must be deleted and recreated. - enum: - - string - - secretString - service: - type: string - example: author - description: 'Service of the variable. When not provided, the variable applies to all services. Currently the values ''author'', ''publish'', and ''preview'' are supported. Note - this value is case-sensitive.' - status: - type: string - example: ready - description: Status of the variable - enum: - - creating - - ready - - deleting - - deleted - - updating - - failed - - deleted_failed - description: A named value than can be set on an Environment or Pipeline - VariableList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - example: 1 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - variables: - type: array - example: '[{ ''name'':''variable1Name'', ''value'':''variable1Value''}, { ''name'':''variable1Name'', ''value'':''variable1Value'', ''service'':''author''}, { ''name'':''variable2Name'', ''type'':''secretString'', ''value'':''variable2SecretValue''}]' - description: Variables set on environment - items: - $ref: '#/definitions/Variable' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/environment': - description: The environment holding the variables - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/pipeline': - description: The pipeline holding the variables - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Program - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - RegionDeployment: - type: object - properties: - cluster: - type: string - example: ethos13stageva7 - description: The cluster where this deployment happens - namespace: - type: string - example: ns-team-aem - description: The namespace in which this deployment happens - createdAt: - type: string - format: date-time - description: Created time - updatedAt: - type: string - format: date-time - description: Date of last change - id: - type: string - description: identifier of a region deployment - environmentId: - type: string - description: identifier of an environment - region: - type: string - example: va7 - description: Region name of the deployment - integrations: - description: region integrations - $ref: '#/definitions/EnvironmentRegionintegrations' - status: - type: string - description: Status of the region deployment - enum: - - PENDING - - PROGRESSING - - FAILED - - COMPLETE - - DELETING - - DELETED - - DELETION_FAILED - - TO_DELETE - - DEPLOY_FAILED - - DEPLOY_TIMEOUT - type: - type: string - example: primary - description: Type of the region deployment - enum: - - PRIMARY - - SECONDARY - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/flow': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/kubernetesCluster': - description: Get the Kubernetes Cluster in which this deployment happens - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/kubernetesNamespace': - description: Get the Kubernetes Namespace in which this deployment happens - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/region': - description: Region being used for this deployment - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: describes region deployments for an environment - RegionDeploymentList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - regionDeployments: - type: array - items: - $ref: '#/definitions/RegionDeployment' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - ContentSet: - type: object - properties: - id: - type: string - example: '123' - description: Identifier of the Content Set - name: - type: string - description: The name of the content set - paths: - type: array - description: Included asset paths - uniqueItems: true - items: - $ref: '#/definitions/ContentSetPath' - programId: - type: string - example: '658' - description: Identifier of the program. Unique within the space. - createdAt: - type: string - format: date-time - description: Create date - readOnly: true - updatedAt: - type: string - format: date-time - description: Update date - readOnly: true - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Application this content set belongs to. - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A representation of a ContentSet custom - ContentSetPath: - type: object - properties: - path: - type: string - description: path - excluded: - type: array - description: excluded - uniqueItems: true - items: - type: string - description: Describes a __Content Set path__ - ContentSetList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - contentSets: - type: array - items: - $ref: '#/definitions/ContentSet' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes a Content Set List representation - ContentFlow: - type: object - properties: - contentSetId: - type: string - description: The content set id - contentSetName: - type: string - description: The content set name - srcEnvironmentId: - type: string - description: Source environment id - srcEnvironmentName: - type: string - description: Source environment name - destEnvironmentId: - type: string - description: Destination environment id - destEnvironmentName: - type: string - description: Destination environment name - tier: - type: string - description: 'The tier, for example author' - status: - type: string - description: Status of the flows - destProgramId: - type: string - description: Destination program id - resultDetails: - description: Details of this content flow result - $ref: '#/definitions/ContentFlowResults' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/contentSet': - description: The Content set for this flow. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Application this content set belongs to. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/environment': - description: The source Environment this content flow is copying from. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/destEnvironment': - description: The destination Environment this content flow is copying to. - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: The Content Flow Execution - ContentFlowResults: - type: object - properties: - exportResult: - description: export results - $ref: '#/definitions/ContentFlowResultDetails' - importResult: - description: import results - $ref: '#/definitions/ContentFlowResultDetails' - transferProgress: - type: string - description: Transfer progress percentage - description: The Content Flow Results - ContentFlowList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - contentFlows: - type: array - items: - $ref: '#/definitions/ContentFlow' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - PipelineStep: - type: object - required: - - name - properties: - name: - type: string - example: deploy - description: Name of the step - options: - type: object - description: Map of option parameters for the step - $ref: '#/definitions/PipelineStepOptions' - description: Describes a step from a phase of a pipeline - SystemUnderMaintenanceExceptionMapper: - type: object - Artifact: - type: object - required: - - stepName - - type - properties: - id: - type: string - example: '29' - description: Identifier of the Artifact - stepName: - type: string - example: loadTest - description: Name of the step - type: - type: string - example: LOAD_ERROR_PAGES - description: Type of the artifact - enum: - - LOG_FILE - - SCAN_ISSUES - - LOAD_ERROR_PAGES - - LOAD_SLOW_PAGES - - LOAD_ERROR_GRAPH_CSV - - LOAD_ERROR_GRAPH_JSON - - LOAD_RESPONSE_TIME_GRAPH_CSV - - LOAD_RESPONSE_TIME_GRAPH_JSON - - LOAD_PEAK_RESPONSE_TIME_GRAPH_JSON - - LOAD_PEAK_RESPONSE_TIME_GRAPH_CSV - - CPU_PERCENT_CSV - - CPU_PERCENT_JSON - - CPU_I_O_WAIT_PERCENT_CSV - - CPU_I_O_WAIT_PERCENT_JSON - - DISK_UTILIZATION_PERCENT_CSV - - DISK_UTILIZATION_PERCENT_JSON - - NETWORK_BANDWIDTH_CSV - - NETWORK_BANDWIDTH_JSON - - SKYLINE_CUSTOMER_IMAGE - - SKYLINE_DISPATCHER_CONFIGURATION - - SIGNED_CONTENT_PACKAGE - - SIGNED_DISPATCHER_CONFIGURATION - - CONTENT_AUDIT_RESULTS - - CONTENT_AUDIT_REPORT - - SKYLINE_UI_TESTS_IMAGE - - SKYLINE_TRANSFORM_JOB_OUTPUT_ARTIFACT - - SKYLINE_TRANSFORM_JOB_OUTPUT_DESCRIPTOR - - CONTENT_PACKAGE - - DISPATCHER_CONFIGURATION - - FONT_ARCHIVE - - UI_TEST_RESULTS - file: - type: string - example: build/code_quality_scan.log - description: File location - format: - type: string - example: text/csv - description: File format - md5: - type: string - example: d41d8cd98f00b204e9800998ecf8427e - description: MD5 hash of the file - _links: - type: object - readOnly: true - properties: - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes an artifact associated with a step - ArtifactList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - artifacts: - type: array - items: - $ref: '#/definitions/Artifact' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes a list of artifacts associated with a step - LogOptionRepresentation: - type: object - required: - - name - - service - properties: - service: - type: string - description: 'Name of the service in environment. Example: author' - name: - type: string - description: 'Name of the log for service in environment. Example: aemerror' - EnvironmentBlobStorageConfiguration: - type: object - required: - - type - properties: - type: - type: string - enum: - - azure_blob - - azure_files - - mongo_atlas - description: Settings for environment blob storage - EnvironmentLogStorageConfiguration: - type: object - required: - - type - properties: - type: - type: string - enum: - - azure_blob - - azure_files - - mongo_atlas - description: Settings for environment log storage - EnvironmentRegionintegrations: - type: object - properties: - blobStorage: - $ref: '#/definitions/EnvironmentBlobStorageConfiguration' - logStorage: - $ref: '#/definitions/EnvironmentLogStorageConfiguration' - description: integrations for a particular EnvironmentRegion - RestorePointDetails: - type: object - properties: - atlasOrganisationId: - type: integer - format: int64 - description: Atlas Organisation ID - atlasClusterId: - type: integer - format: int64 - description: Atlas cluster ID - restorePoint: - type: integer - format: int64 - description: Restore point - deploymentDate: - type: string - format: date-time - description: The date when the deployment was made - deploymentHistoryId: - type: integer - format: int64 - description: The Helm Deployment History ID - aemReleaseVersion: - type: string - description: AEM release version - repositoryId: - type: string - description: Git repository ID - repositoryName: - type: string - description: Git repository name - repositoryUrl: - type: string - description: Git repository URL - branchName: - type: string - description: Git branch name - commitHash: - type: string - description: Git commit hash - restoreDate: - type: string - format: date-time - description: Restore date - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/atlascluster': - $ref: '#/definitions/HalLink' - RestorePointsList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - restorePointsDetails: - type: array - description: restorePointsDetails - items: - $ref: '#/definitions/RestorePointDetails' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - ErrorDetailsRepresentation: - type: object - properties: - errorCode: - type: string - description: The error code - readOnly: true - publicDetails: - type: object - description: Additional error details that can be used by customer - additionalProperties: - type: object - readOnly: true - message: - type: string - description: Human readable error message - readOnly: true - Restore-Environmentdetailsrepresentation: - type: object - properties: - releaseId: - type: string - repositoryId: - type: string - repositoryName: - type: string - branch: - type: string - commitSha: - type: string - repositoryUrl: - type: string - timestamp: - type: integer - format: int64 - RestoreExecution: - type: object - properties: - id: - type: string - description: id - programId: - type: string - example: '14' - description: 'Identifier of the program, unique within the space' - environmentId: - type: string - example: '14' - description: 'Identifier of the environment, unique within the space' - status: - type: string - example: not_started - description: Status of the restore execution - enum: - - not_started - - running - - finished - - error - - failed - errorDetails: - description: 'Error details, present only when execution failed' - $ref: '#/definitions/ErrorDetailsRepresentation' - environmentDetailsAtSnapshotDate: - description: Environment details at snapshot timestamp - $ref: '#/definitions/Restore-Environmentdetailsrepresentation' - environmentDetailsAtRestoreDate: - description: Environment details when the restore was triggered - $ref: '#/definitions/Restore-Environmentdetailsrepresentation' - createdAt: - type: string - format: date-time - description: createdAt - updatedAt: - type: string - format: date-time - description: updatedAt - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/environment': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/flow': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Application this environment belongs to - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/restoreExecution/logs/download': - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: A RestoreExecution - RestoreExecutionLimit: - type: object - properties: - resetDate: - type: string - format: date - description: Reset date - available: - type: integer - format: int64 - description: Available runs until reset - max: - type: integer - format: int64 - description: Max runs per interval - countInterval: - type: integer - format: int64 - description: Rolling window used to count the available runs - RestoreExecutionList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int64 - description: The total number of embedded items - limits: - description: Restore executions limits - $ref: '#/definitions/RestoreExecutionLimit' - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - restoreExecutions: - type: array - items: - $ref: '#/definitions/RestoreExecution' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - RestoreParamRepresentation: - type: object - required: - - pointInTimeInMillis - properties: - pointInTimeInMillis: - type: string - description: Desired point in time - pattern: '\d{1,19}$' - IPAllowedListBinding: - type: object - required: - - environmentId - properties: - id: - type: integer - format: int64 - example: 14 - description: Identifier of the IP Allowed List Binding to an Environment - tier: - type: string - example: publish - description: Tier of the environment. - enum: - - PUBLISH - - PREVIEW - status: - type: string - example: NOT_STARTED - description: Status of the binding. - programId: - type: integer - format: int64 - example: 22 - description: Identifier of the program. - ipAllowListId: - type: integer - format: int64 - example: 17 - description: Identifier of the IP allow list. - environmentId: - type: integer - format: int64 - example: 5 - description: Identifier of the environment. - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Application this environment belongs to. - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/ipAllowList': - description: IpAllowList to be binded to the environment. - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes an __IP Allowed List Binding__ - IPAllowedList: - type: object - required: - - ipCidrSet - - name - properties: - id: - type: integer - format: int64 - example: 14 - description: Identifier of the IP Allowed List - name: - type: string - example: NewYork Office - description: Name of the IP Allowed List - programId: - type: integer - format: int64 - example: 22 - description: Identifier of the program. - ipCidrSet: - type: array - example: '["11.22.33.44/28", "99.88.77.66/32"]' - description: IP CIDR Set - uniqueItems: true - items: - type: string - maxItems: 50 - minItems: 1 - bindings: - type: array - description: IP Allowlist bindings - items: - $ref: '#/definitions/IPAllowedListBinding' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/ipAllowlistBindings': - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/program': - description: The Application this environment belongs to. - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes an __IP Allowed List__ - Updateanipallowlist: - type: object - required: - - ipCidrSet - - name - properties: - name: - type: string - example: NewYork Office - description: Name of the IP Allowed List - ipCidrSet: - type: array - example: '["11.22.33.44/28", "99.88.77.66/32"]' - description: IP CIDR Set - uniqueItems: true - items: - type: string - maxItems: 50 - minItems: 1 - IPAllowlistBindingsList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - ipAllowlistId: - type: string - _embedded: - type: object - readOnly: true - properties: - ipAllowlistBindings: - type: array - items: - $ref: '#/definitions/IPAllowedListBinding' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - IPAllowlistList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - ipAllowlists: - type: array - items: - $ref: '#/definitions/IPAllowedList' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - Createanewipallowlist: - type: object - required: - - ipCidrSet - - name - properties: - name: - type: string - example: NewYork Office - description: Name of the IP Allowed List - ipCidrSet: - type: array - example: '["11.22.33.44/28", "99.88.77.66/32"]' - description: IP CIDR Set - uniqueItems: true - items: - type: string - maxItems: 50 - minItems: 1 - Domain: - type: object - required: - - label - - programId - properties: - deleted: - type: boolean - default: false - id: - type: integer - format: int64 - description: id - domainName: - type: string - example: customer.domain.com - description: Name of the domain name - label: - type: string - description: Domain label - programId: - type: integer - format: int64 - description: Id of the program - createdAt: - type: integer - format: int64 - description: Create date - updatedAt: - type: integer - format: int64 - description: Last updated date - deletedAt: - type: integer - format: int64 - description: Deleted At - acmeValidationStatus: - type: string - example: NOT_VERIFIED - description: Acme Validation Status - adobeValidationStatus: - type: string - example: NOT_VERIFIED - description: Adobe Validation Status - acmeValidationToken: - type: string - description: Acme Validation Token - adobeValidationToken: - type: string - description: Adobe Validation Token - description: A Domain representation - UpdateaDomain'snameorlabel: - type: object - required: - - label - properties: - label: - type: string - example: any string - description: Domain label - DomainCreate: - type: object - properties: - domainName: - type: string - example: customer.domain.com - description: Name of the domain name - description: A Domain representation for creating a domain - DomainTokenValidationBody: - type: object - properties: - validationType: - type: string - example: acme - description: Type of the validation - enum: - - acme - - adobe - description: The json body for token validation - DomainMapping: - type: object - properties: - domainMappingId: - type: integer - format: int64 - description: Domain Mapping ID - programId: - type: integer - format: int64 - description: Identifier of the CM Program - originId: - type: integer - format: int64 - description: Id of either EDS site or Skyline Environment - domainMappingStatus: - type: string - description: Status of the domain mapping - domainName: - type: string - description: Name of the domain - originType: - type: string - description: 'Type of origin: EDS_SITE or SKYLINE_ENVIRONMENT' - tier: - type: string - description: 'Type of tier: PREVIEW or PUBLISH' - enum: - - PUBLISH - - PREVIEW - - AUTHOR - - STATIC - - DELIVERY - domainId: - type: integer - format: int64 - description: Id of the domain - certificateId: - type: integer - format: int64 - description: Id of the certificate - createdAt: - type: integer - format: int64 - description: Creation date - updatedAt: - type: integer - format: int64 - description: Last modification date - deletedAt: - type: integer - format: int64 - description: Deletion date - description: Describes a domain mapping - Updateadomainmapping: - type: object - required: - - certificateId - - tier - properties: - certificateId: - type: integer - format: int64 - description: Certificate ID - tier: - type: string - description: 'Type of tier: PREVIEW or PUBLISH' - enum: - - PUBLISH - - PREVIEW - - AUTHOR - - STATIC - - DELIVERY - DomainMappingList: - type: object - properties: - totalNumberOfItems: - type: integer - format: int32 - domainMappings: - type: array - items: - $ref: '#/definitions/DomainMapping' - Createanewdomainmapping: - type: object - required: - - certificateId - - domainId - - originId - - originType - - tier - properties: - originId: - type: integer - format: int64 - description: 'Origin ID: EDS or Skyline Environment ID' - domainId: - type: integer - format: int64 - description: Domain ID - certificateId: - type: integer - format: int64 - description: Certificate ID - tier: - type: string - description: 'Type of the tier: PREVIEW or PUBLISH' - enum: - - PUBLISH - - PREVIEW - originType: - type: string - description: 'Type of the origin: EDS_SITE or SKYLINE_ENVIRONMENT' - enum: - - EDS_SITE - - SKYLINE_ENVIRONMENT - SslCertificateRepresentation: - type: object - properties: - id: - type: integer - format: int64 - description: id - sslCertificateType: - type: string - description: 'Type of origin: DV, EV or OV' - sslCertificateStatus: - type: string - description: 'PENDING, VALID or EXPIRED' - programId: - type: integer - format: int64 - example: 14 - description: Identifier of the application. Unique within the space. - serialNumber: - type: string - description: Unique identifier of the certificate at CA level. - name: - type: string - example: Certificate Name Example - description: Name of the SSL Certificate. - issuer: - type: string - description: Issuer of the SSL Certificate. - expireAt: - type: integer - format: int64 - description: Expiration date of the SSL Certificate. - commonName: - type: string - description: Common name of the SSL Certificate. - subjectAlternativeNames: - type: array - description: Subject alternative names of the SSL Certificate. - items: - type: string - certificate: - type: string - description: Encrypted content of the SSL Certificate. - chain: - type: string - description: Content of the Chain File. - createdAt: - type: integer - format: int64 - description: Date of SSL Certificate submission. - updatedAt: - type: integer - format: int64 - description: Date of last SSL Certificate update. - _links: - type: object - readOnly: true - properties: - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes an SSL Certificate - SslCertificateNotFoundException: - type: object - properties: - message: - type: string - localizedMessage: - type: string - SecretString: - type: object - properties: - value: - type: string - example: my-secret - description: 'Secret value for updating the secrets, null for not updating the existing secret' - path: - type: string - CreateOrUpdateSslCertificateBody: - type: object - required: - - name - - certificate - - privateKey - - chain - properties: - name: - type: string - description: The name of the new SSL Certificate. - certificate: - type: string - description: The PEM-encoded certificate. - privateKey: - type: object - properties: - value: - type: string - description: Private key value - description: The PEM-encoded private key. - chain: - type: string - description: The PEM-encoded certificate chain. - AllSSLCertificatesList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _page: - $ref: '#/definitions/RequestedPageDetails' - description: Details of the requested page of items - _embedded: - type: object - readOnly: true - properties: - certificates: - type: array - items: - $ref: '#/definitions/SslCertificateRepresentation' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - page: - $ref: '#/definitions/HalLink' - description: An arbitrary page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - CreateDvCertificateBody: - type: object - required: - - domainIds - properties: - name: - type: string - example: my-cert - description: Name of the certificate - domainIds: - type: array - description: List of domain IDs to associate with the certificate - items: - type: integer - format: int64 - SslCertificate: - type: object - properties: - id: - type: integer - format: int64 - sslCertificateType: - type: string - enum: - - DV - - EV - - OV - programId: - type: integer - format: int64 - serialNumber: - type: string - name: - type: string - certificate: - type: string - issuer: - type: string - expireAt: - type: integer - format: int64 - privateKeyPath: - type: string - commonName: - type: string - commonNameRegex: - type: string - subjectAlternativeNames: - type: array - items: - type: string - subjectAlternativeNamesRegex: - type: array - items: - type: string - chain: - type: string - createdAt: - type: integer - format: int64 - updatedAt: - type: integer - format: int64 - deletedAt: - type: integer - format: int64 - externalId: - type: integer - format: int64 - sslCertificateStatus: - type: string - enum: - - PENDING - - VALID - - EXPIRED - Site: - type: object - properties: - siteId: - type: integer - format: int64 - description: siteId - programId: - type: string - description: Identifier of the CM Program ID. Unique within the space. - siteName: - type: string - description: Name of the site - repoUrl: - type: string - description: CM Eds Site Repo URL. - siteStatus: - type: string - description: Site EDS status - validationToken: - type: string - description: Validation token of the CM EDS Site - createdAt: - type: integer - format: int64 - description: Creation date - modifiedAt: - type: integer - format: int64 - description: Last modification date - deletedAt: - type: integer - format: int64 - description: Deleted date - deleted: - type: boolean - description: deleted or not - default: false - _links: - type: object - readOnly: true - properties: - self: - $ref: '#/definitions/HalLink' - description: This object's representation - sites: - $ref: '#/definitions/HalLink' - description: Describes a Site - SiteList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - sites: - type: array - items: - $ref: '#/definitions/Site' - _links: - type: object - readOnly: true - properties: - self: - $ref: '#/definitions/HalLink' - description: This object's representation - NewRelicSub-AccountUser: - type: object - properties: - id: - type: string - example: '42' - description: Identifier of the New Relic sub account User - firstName: - type: string - example: John - description: First name of the New Relic sub account User - lastName: - type: string - example: Doe - description: Last name of the New Relic sub account User - email: - type: string - example: foobar@newrelic.com - description: email of the New Relic sub account user - role: - type: string - example: admin - description: Role of the New Relic sub account user - owner: - type: boolean - example: false - description: Owner detail of the New Relic sub account User - default: false - description: Describes __New Relic Sub-Account User__ - NewRelicSubAccountUserlist: - type: object - properties: - _totalNumberOfNewRelicSubAccountUsers: - type: integer - format: int32 - applicationId: - type: string - example: '44' - description: The id of the Cloud Manager application this sub account user list is linked to - _embedded: - type: object - readOnly: true - properties: - newRelicUsers: - type: array - items: - $ref: '#/definitions/NewRelicSub-AccountUser' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/application': - description: Application linked to this New Relic sub account - $ref: '#/definitions/HalLink' - 'http://ns.adobe.com/adobecloud/rel/newRelicSubAccount': - description: New Relic sub account linked to the New Relic sub account User list - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: List of New Relic sub account users - Organisation: - type: object - properties: - organizationName: - type: string - example: adobecloudmanager-acmeCorp - description: Name of the git repository organization - minLength: 0 - maxLength: 50 - status: - type: string - example: creating - description: Status of the organisation on-boarding process - enum: - - not_started - - creating - - ready - - failed - description: Organisation details - Tenant: - type: object - required: - - imsOrgId - - imsTenantId - properties: - id: - type: string - example: '14' - description: Identifier of the tenant - imsOrgId: - type: string - example: 1AAA222B3C4444D55E666666@AdobeOrg - description: IMS Organization of this tenant - minLength: 0 - maxLength: 255 - imsTenantId: - type: string - example: acmeCorp - description: IMS Tenant Id - minLength: 0 - maxLength: 255 - description: - type: string - example: Description for acmeCorp - description: Description of the tenant - minLength: 0 - maxLength: 255 - status: - type: string - example: creating - description: Status of the tenant - enum: - - creating - - ready - - failed - organisation: - description: Tenant-level git repository organisation - $ref: '#/definitions/Organisation' - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/programs': - description: Programs defined in the tenant - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes a __Tenant__ - TenantList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - tenants: - type: array - items: - $ref: '#/definitions/Tenant' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - Region: - type: object - properties: - name: - type: string - example: va7 - description: Region name - _links: - type: object - readOnly: true - properties: - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes a __Region__ - RegionsList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - regions: - type: array - items: - $ref: '#/definitions/Region' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - DnsConfiguration: - type: object - required: - - resolvers - properties: - resolvers: - type: array - description: List of remote DNS resolvers - items: - type: string - description: DNS Information. Only applicable to VPN infrastructures. - GatewayInfrastructure: - type: object - required: - - address - - addressSpace - properties: - address: - type: string - description: Customer VPN Device IP Address - addressSpace: - type: array - description: IP Ranges to route through the VPN - items: - type: string - IpSecPolicyInfrastructure: - type: object - required: - - dhGroup - - ikeEncryption - - ikeIntegrity - - ipsecEncryption - - ipsecIntegrity - - pfsGroup - - saDatasize - - saLifetime - properties: - dhGroup: - type: string - description: DH Group - enum: - - DHGroup24 - - ECP384 - - ECP256 - - DHGroup14 - - DHGroup2048 - - DHGroup2 - - DHGroup1 - - None - ikeEncryption: - type: string - description: IKEv2 Encryption - enum: - - AES256 - - AES192 - - AES128 - - DES3 - - DES - ikeIntegrity: - type: string - description: IKEv2 Integrity - enum: - - SHA384 - - SHA256 - - SHA1 - - MD5 - ipsecEncryption: - type: string - description: IPsec Encryption - enum: - - GCMAES256 - - GCMAES192 - - GCMAES128 - - AES256 - - AES192 - - AES128 - - DES3 - - DES - - None - ipsecIntegrity: - type: string - description: IPsec Integrity - enum: - - GCMAES256 - - GCMAES192 - - GCMAES128 - - SHA256 - - SHA1 - - MD5 - pfsGroup: - type: string - description: PFS Group - enum: - - PFS24 - - ECP384 - - ECP256 - - PFS2048 - - PFS2 - - PFS1 - - None - saDatasize: - type: integer - format: int64 - description: QM SA Lifetime in KBytes under 1024 - minimum: 1024 - saLifetime: - type: integer - format: int32 - description: 'QM SA Lifetime in Seconds, minimum 300' - minimum: 300 - VpnConnection: - type: object - required: - - gateway - - ipsecPolicy - - name - - sharedKey - properties: - name: - type: string - description: Name of the connection - gateway: - description: Gateway configuration - $ref: '#/definitions/GatewayInfrastructure' - sharedKey: - type: string - description: Customer VPN preshared key - ipsecPolicy: - description: IPSec Policy - $ref: '#/definitions/IpSecPolicyInfrastructure' - NetworkInfrastructure: - type: object - required: - - kind - - region - properties: - kind: - type: string - description: Kind of the infrastructure - enum: - - vpn - - dedicatedEgressIp - - flexiblePortEgress - id: - type: string - description: id - readOnly: true - programId: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - readOnly: true - status: - type: string - example: creating - description: Status of the network configuration - enum: - - creating - - failed - - updating - - deleting - - deleted - - ready - - error - readOnly: true - region: - type: string - example: va6 - description: 'Region to create the infrastructure. Use your primary region, whose identifier can be retrieved from the [List Regions endpoint](#operation/getProgramRegions).' - isPrimaryRegion: - type: boolean - description: Boolean property to mark whether network infrastructure being created is for primary region or not. - default: false - created: - type: string - format: date-time - description: Creation date - readOnly: true - updated: - type: string - format: date-time - description: Last modification date - readOnly: true - addressSpace: - type: array - description: A list of CIDRs. It can only be one /26 CIDR (64 IP addresses) or bigger IP range in the customer space. Cannot be changed later. Only applicable to VPN. - items: - type: string - dns: - description: DNS Information. Only applicable to VPN infrastructures. - $ref: '#/definitions/DnsConfiguration' - connections: - type: array - description: List of VPN connections - items: - $ref: '#/definitions/VpnConnection' - statusDetails: - description: Error details. Present only when failed operations. - $ref: '#/definitions/ErrorDetailsRepresentation' - readOnly: true - _links: - type: object - readOnly: true - properties: - 'http://ns.adobe.com/adobecloud/rel/program': - $ref: '#/definitions/HalLink' - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: An network infrastructure representation - NetworkInfrastructuresList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - networkInfrastructures: - type: array - items: - $ref: '#/definitions/NetworkInfrastructure' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - PortForwardRepresentation: - type: object - required: - - portDest - - portOrig - properties: - name: - type: string - example: smtp.example.com - description: Destination host - pattern: '^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$' - portDest: - type: integer - format: int32 - example: 443 - description: Destination port - maximum: 65535 - portOrig: - type: integer - format: int32 - example: 30710 - description: Origin port for tunnel. Must be unique and in 30000-31000 range. - minimum: 30000 - maximum: 31000 - AdvancedNetworkingConfiguration: - type: object - properties: - programId: - type: string - example: '14' - description: Identifier of the program. Unique within the space. - readOnly: true - environmentId: - type: string - description: Identifier of the environment. Unique within the space. - readOnly: true - networkInfrastructureId: - type: string - example: '123' - description: Advanced network infrastructure used. - readOnly: true - nonProxyHosts: - type: array - description: 'A list of hosts that should be reached directly, bypassing the special VPN or egress routing. The patterns may start or end with a ''''*'''' for wildcards.' - items: - type: string - example: - - '*.example.com' - - '*.example.net' - portForwards: - type: array - description: List of port forwarding rules - items: - $ref: '#/definitions/PortForwardRepresentation' - advancedNetworkingEnabled: - type: boolean - description: Whether advanced networking is enabled in this environment - default: false - readOnly: true - _links: - type: object - readOnly: true - properties: - self: - $ref: '#/definitions/HalLink' - description: This object's representation - description: Describes the Advanced Networking configuration for an environment - AdvancedNetworkingConfigurationList: - type: object - properties: - _totalNumberOfItems: - type: integer - format: int32 - description: The total number of embedded items - _embedded: - type: object - readOnly: true - properties: - networkingConfigurations: - type: array - items: - $ref: '#/definitions/AdvancedNetworkingConfiguration' - _links: - type: object - readOnly: true - properties: - next: - $ref: '#/definitions/HalLink' - description: The next page of results. - prev: - $ref: '#/definitions/HalLink' - description: The previous page of results. - self: - $ref: '#/definitions/HalLink' - description: This object's representation - ContentFlowValidationErrors: - type: object - properties: - errorCode: - type: string - description: content flow warning error code - message: - type: string - description: content flow warning message - details: - type: array - description: details - items: - type: string - description: The Content Flow Validation Errors - ContentFlowInfo: - type: object - properties: - validationErrors: - type: array - description: validationErrors - items: - $ref: '#/definitions/ContentFlowValidationErrors' - description: The Content Flow Info - ContentFlowResultDetails: - type: object - properties: - errorCode: - type: string - description: content flow error - message: - type: string - description: content flow error message - details: - type: array - description: details - items: - type: string - info: - description: info - $ref: '#/definitions/ContentFlowInfo' - phase: - type: string - description: phase - description: The Content Flow Result Details - ContentFlowInput: - type: object - properties: - contentSetId: - type: string - destEnvironmentId: - type: string - tier: - type: string - example: author - description: tier - includeACL: - type: boolean - description: includeACL - default: false - destProgramId: - type: string - description: destProgramId - mergeExcludePaths: - type: boolean - description: mergeExcludePaths - default: false - copyVersions: - type: boolean - description: copyVersions - default: false - description: Wraps the content flow execution arguments - CompatibilityCheckInput: - type: object - required: - - destinationEnvironmentId - - sourceEnvironmentId - properties: - sourceEnvironmentId: - type: string - destinationEnvironmentId: - type: string - tier: - type: string - enum: - - PUBLISH - - AUTHOR - description: Wraps the content copy compatibility check execution arguments. - CompatibilityCheckResponse: - type: object - properties: - sourceEnvironmentId: - type: string - example: '1234' - description: The source environment ID - sourceTopologyId: - type: string - example: 1a2b3cd4 - description: The source topology ID - destinationEnvironmentId: - type: string - example: '5678' - description: The destination environment ID - destinationTopologyId: - type: string - example: 1a2b3cd4 - description: The destination topology ID - tier: - type: string - example: author - description: tier - overallResult: - type: string - example: PASS - description: The overall result of the compatibility check - overallMessage: - type: string - example: Destination Topology cannot be prod. - description: The overall response message of the compatibility check - failedValidation: - type: string - example: TIER_NOT_ALLOWED - description: Error Code for the Failed Compatibility Check - enum: - - SOURCE_DISK_ORG - - TARGET_DISK_ORG - - SOURCE_REPO_TYPE - - TARGET_REPO_TYPE - - DATASTORE_TYPE - - BLOCK_TYPE - - TARGET_ENV - - REGION_CRITERIA - - CONNECTION_ERROR - - UNSUPPORTED_SKYLINE_ENV - - BAD_REQUEST - - ENVIRONMENT_NOT_FOUND - - PROGRAM_NOT_FOUND - - TIER_NOT_ALLOWED - - UNKNOWN - responseStatusCode: - type: integer - format: int32 - description: Describes the Backflow Compatibility between two topologies. - ContentFlowLog: - type: object - properties: - jobType: - type: string - example: (import or export) - description: job type - programId: - type: integer - format: int64 - contentFlowId: - type: integer - format: int64 - _links: - type: object - readOnly: true - properties: - download: - description: Download Logs link - $ref: '#/definitions/HalLink' - logs/tail: - description: Tail Log link - $ref: '#/definitions/HalLink' - description: Log from Content Flow - Redirect: - type: object - required: - - redirect - properties: - redirect: - type: string - description: The url to redirect to. - NewFeedback: - type: object - required: - - rating - - type - properties: - createdAt: - type: string - description: Created time - id: - type: integer - description: Identifier of the feedback. Unique within the space. - rating: - type: integer - description: Rating values from 1 to 5 - comment: - type: string - description: Feedback comment - type: - type: string - description: Type of feedback - enum: - - GO_LIVE - options: - type: object - description: Optional information about the feedback - description: Describes feedback - GoLiveDates: - type: object - properties: - plannedDate: - type: string - description: Date when go live is planned - actualDate: - type: string - description: Date when the program completed go live - description: Contains planned and actual go live dates of a program - PipelineUpdate: - type: object - description: Describe an update to a pipeline - properties: - phases: - type: array - description: Pipeline phases to update - items: - $ref: '#/definitions/PipelinePhaseUpdate' - EnvironmentVariableUpdate: - type: object - properties: - name: - type: string - example: MY_VAR1 - description: 'Name of the variable. Can only consist of a-z, A-Z, _ and 0-9 and cannot begin with a number.' - minLength: 2 - maxLength: 100 - pattern: '[a-zA-Z_][a-zA-Z_0-9]*' - value: - type: string - example: myValue - description: 'Value of the variable. Read-Write for non-secrets, write-only for secrets. The length of `secretString` values must be less than 500 characters. An empty value causes a variable to be deleted.' - minLength: 0 - maxLength: 2048 - type: - type: string - example: string - description: Type of the variable. Default `string` if missing. `secretString` variables are encrypted at rest. The type of a variable be changed after creation; the variable must be deleted and recreated. - enum: - - string - - secretString - service: - type: string - example: author - description: 'Service of the variable. When not provided, the variable applies to all services. Currently the values ''author'', ''publish'', and ''preview'' are supported. Note - this value is case-sensitive.' - description: 'A change (create, update, delete) of a named value on an Environment' - PipelineVariableUpdate: - type: object - properties: - name: - type: string - example: MY_VAR1 - description: 'Name of the variable. Can only consist of a-z, A-Z, _ and 0-9 and cannot begin with a number.' - minLength: 2 - maxLength: 100 - pattern: '[a-zA-Z_][a-zA-Z_0-9]*' - value: - type: string - example: myValue - description: 'Value of the variable. Read-Write for non-secrets, write-only for secrets. The length of `secretString` values must be less than 500 characters. An empty value causes a variable to be deleted.' - minLength: 0 - maxLength: 2048 - type: - type: string - example: string - description: Type of the variable. Default `string` if missing. `secretString` variables are encrypted at rest. The type of a variable be changed after creation; the variable must be deleted and recreated. - enum: - - string - - secretString - description: 'A change (create, update, delete) of a named value on a Pipeline' - PipelinePhaseUpdate: - type: object - required: - - type - description: Describes an update to a phase of a pipeline - properties: - name: - type: string - example: BUILD_1 - description: Name of the phase - type: - type: string - example: BUILD - description: Type of the phase - enum: - - BUILD - - DEPLOY - repositoryId: - type: string - description: 'For BUILD phase type. Identifier of the source repository. The code from this repository will be build at the start of this phase. If not provided, the current value is retained.' - branch: - type: string - description: 'For BUILD phase type. Name of the tracked branch or a fully qualified git tag (e.g. refs/tags/v1). If not provided, the current value is retained.' - environmentId: - type: string - description: For DEPLOY phase type. Identifier of the target environment. - steps: - type: array - description: Steps to update within the phase. - items: - $ref: '#/definitions/PipelineStepUpdate' - PipelineStepUpdate: - type: object - required: - - type - description: Describes an update to a phase of a pipeline - properties: - name: - type: string - example: deploy - description: Name of the step - options: - type: object - description: Map of option parameters for the step - $ref: '#/definitions/PipelineStepUpdateOptions' - PipelineStepUpdateOptions: - type: object - properties: - dispatcherCacheInvalidationPaths: - type: array - items: - type: string - description: 'For deploy steps on AMS pipelines, list of paths to invalidate on dispatchers after package installation.' - dispatcherCacheFlushPaths: - type: array - items: - type: string - description: 'For deploy steps on AMS pipelines, list of paths to flush on dispatchers after package installation.' - EnableAdvancedNetworkingConfiguration: - type: object - properties: - nonProxyHosts: - type: array - description: 'A list of hosts that should be reached directly, bypassing the special VPN or egress routing. The patterns may start or end with a ''''*'''' for wildcards.' - items: - type: string - example: - - '*.example.com' - - '*.example.net' - portForwards: - type: array - description: List of port forwarding rules - items: - $ref: '#/definitions/PortForwardRepresentation' - PipelineExecutionStepStateDetails: - type: object - description: Details available for each step state. The set of properties available will vary by the step action. - properties: - deployCommands: - type: string - description: 'For deploy steps, a JSON array encoded as a string which lists the deployment activities expected to be performed.' - currentDeployCommandId: - type: string - description: 'For deploy steps, the current identifier from the deployCommands which is being executed.' - environmentUrls: - type: array - description: 'For deploy steps, the the set of URLs for the environment.' - items: - type: object - properties: - instanceType: - type: string - instanceUrl: - type: string - deploymentStepDescription: - type: string - description: 'For deploy steps, a JSON array encoded as a string which includes the detailed list of deployment activities which have been performed.' - input: - type: object - description: 'Input provided when advancing the step. See documentation at https://www.adobe.io/experience-cloud/cloud-manager/guides/api-usage/advancing-and-cancelling-steps/ for details.' - PipelineStepOptions: - type: object - description: Options for a pipeline step. Will vary based on step action and platform. - properties: - skipDetachingDispatchers: - type: boolean - description: 'For deploy steps on AMS pipelines, if true will not detach dispatcher from the load balancer.' - dispatcherCacheInvalidationPaths: - type: array - items: - type: string - description: 'For deploy steps on AMS pipelines, list of paths to invalidate on dispatchers after package installation.' - dispatcherCacheFlushPaths: - type: array - items: - type: string - description: 'For deploy steps on AMS pipelines, list of paths to flush on dispatchers after package installation.' - cse: - type: string - enum: - - MY_CSE - - ANY_CSE - description: 'For managed steps on AMS pipelines, which CSE will be responsible for CSE oversight.' - popularPagesWeight: - type: integer - format: int32 - description: 'For loadTest steps on AMS pipelines, the percentage of performance test traffic which will be sent to the popular pages bucket.' - newPagesWeight: - type: integer - format: int32 - description: 'For loadTest steps on AMS pipelines, the percentage of performance test traffic which will be sent to the new pages bucket.' - otherPagesWeight: - type: integer - format: int32 - description: 'For loadTest steps on AMS pipelines, the percentage of performance test traffic which will be sent to the other pages bucket.' - imageAssetsWeight: - type: integer - format: int32 - description: 'For assetsTest steps on AMS pipelines, the percentage of asset uploads which will be test images.' - pdfAssetsWeight: - type: integer - format: int32 - description: 'For assetsTest steps on AMS pipelines, the percentage of asset uploads which will be test PDF files.' - NewProgram: - type: object - required: - - name - - type - description: Description of a new program to be created - properties: - name: - type: string - description: New program name - minLength: 0 - maxLength: 64 - type: - type: string - enum: - - aem_cloud_service - capabilities: - $ref: '#/definitions/ProgramCapabilities' - solutionNames: - type: array - description: List of solutions to be enabled on the new program. - items: - type: string - enum: - - aemsites - - aemassets - goLive: - description: Go live dates - $ref: '#/definitions/GoLiveDates' - NewEnvironment: - type: object - description: Description of a new program to be created - required: - - name - - region - - type - properties: - name: - type: string - example: acme-dev1 - description: Name of the environment - type: - type: string - enum: - - dev - - stage - - prod - - rde - region: - type: string - example: va7 - description: Region to create the environment. - description: - type: string - example: This is our primary development environment - description: Description of the environment - NewRegionDeployment: - type: object - description: Description of a new region deployment to be added in the environment - required: - - region - properties: - region: - type: string - example: va7 - description: Region to be added in the environment - RegionDeploymentDeletion: - type: object - description: Description of region deployment to be deleted in the environment - required: - - id - - status - properties: - id: - type: string - description: Identifier of the region deployment - status: - type: string - example: TO_DELETE - description: Status of the region deployment to be set - NewRelicSubAccountUser: - type: object - properties: - id: - type: string - example: '42' - description: Identifier of the New Relic sub account User - firstName: - type: string - example: John - description: First name of the New Relic sub account User - lastName: - type: string - example: Doe - description: Last name of the New Relic sub account User - email: - type: string - example: foobar@newrelic.com - description: email of the New Relic sub account user - role: - type: string - example: admin - description: Role of the New Relic sub account user - owner: - type: boolean - example: false - description: Owner detail of the New Relic sub account User - default: false - description: Describes __New Relic Sub-Account User__ - NewContentSet: - type: object - properties: - name: - type: string - description: The name of this content set. - description: - type: string - description: The description of this content set. - paths: - type: array - description: Included asset paths - items: - $ref: '#/definitions/ContentSetPath' - ContentFlowLogs: - type: object - properties: - download: - $ref: '#/definitions/Redirect' - description: link to download logs - logs/tail: - $ref: '#/definitions/Redirect' - description: link to download tails log diff --git a/docsource/aemcm.md b/docsource/aemcm.md new file mode 100644 index 0000000..c7150a8 --- /dev/null +++ b/docsource/aemcm.md @@ -0,0 +1,106 @@ +## Overview + +The `AEMCM` certificate store type represents a single **Adobe Cloud Manager program**. When you define a +certificate store of this type, its Store Path is the numeric `programId`, and the store manages every +customer-managed (OV/EV) SSL certificate in that program through the Cloud Manager API. + +The certificate **alias is the Adobe certificate name**. It is supplied at enrollment, stored as the certificate's +name in Cloud Manager, and reported back by inventory, so aliases round-trip between enrollment and inventory. Name +uniqueness within a program is enforced on enrollment. + +Caveats specific to this store type: + +- A program is limited to **70 installed certificates** (including Adobe-managed DV and expired certificates) and + each certificate to **100 SANs**. To conserve this budget the extension updates an existing certificate when it + can, rather than creating duplicates. +- Adobe-managed (DV) certificates are **read-only**; the extension will not modify or remove them. + +## Requirements + +Before creating certificate stores of this type: + +1. Configure an Adobe IMS **OAuth Server-to-Server** credential with the **Business Owner** or **Deployment + Manager** role, as described in the extension-wide Requirements section. +2. Record the credential's **Client ID**, **Client Secret**, and **IMS Organization ID**. +3. Identify the Cloud Manager **`programId`** for each program you intend to manage (a Discovery job can find these + for you). + +Credentials map to the store fields as follows: **Server Username** = IMS Client ID, **Server Password** = IMS +Client Secret, and the **IMS Organization ID** custom field = your IMS Org ID. + +## Discovery Job Configuration + +Discovery enumerates the Cloud Manager programs your credential can access and returns each as a discoverable +store path (a `programId`). + +Because a Discovery job has no certificate store, the store's custom fields (including the IMS Org ID) are not +available on the discovery form. Provide the Org ID(s) through the standard discovery fields instead: + +- **Client Machine**: the Cloud Manager base URL, `https://cloudmanager.adobe.io`. +- **Server Username / Password**: the IMS Client ID / Client Secret. +- **Directories to Search**: one or more **comma-separated IMS Organization IDs**. This field is required — with no + value the job cannot determine which organization's tenants and programs to enumerate. + +For each Org ID, the job lists the organization's tenants (`GET /api/tenants`) and then each tenant's programs +(`GET /api/tenant/{tenantId}/programs`), returning every `programId`. Approve a result to create an `AEMCM` +certificate store for that program. + +## Certificate Operations + +### Inventory + +Inventory pages through all certificates in the program and reports every one — including Adobe-managed (DV) and +expired certificates — so the 70-certificate limit is visible. Certificate type, status, common name, SANs, and +expiration are surfaced as entry parameters. DV certificates are reported read-only. + +### Add / Enrollment + +Provide an alias; it becomes the Adobe certificate name. Enrolling a name that already exists in the program +**fails unless _Overwrite_ is enabled**, in which case the matching certificate is updated in place. To conserve +the 70-certificate budget, an incoming certificate that matches an existing one by alias or by an identical SAN set +updates that certificate rather than creating a duplicate. If the program is at the 70-certificate limit and no +existing certificate matches, the job fails with guidance to remove expired or unused certificates. Key type +(RSA-2048 or EC secp256r1/secp384r1) and the 100-SAN limit are validated before upload. + +### Remove + +Removing a certificate deletes it from the program. If the certificate is still referenced by one or more domain +mappings, the job fails and lists the offending mapping(s) — remove the mapping(s) first, then retry, and run the +pipeline afterward to fully undeploy. Adobe-managed (DV) certificates cannot be removed. + +## Domain Mappings and Certificate Bindings + +In Cloud Manager, a certificate only serves live traffic once a **domain mapping** (CDN configuration) +associates a domain with it. This extension manages **certificates only** — it does not create, update, or +delete domain mappings. Bindings are managed in Cloud Manager (or through the Cloud Manager domain-mapping APIs) +outside of Keyfactor. This has several implications worth understanding: + +- **Enrollment installs a certificate; it does not bind it.** Adding a certificate uploads it to the program and + makes it available, but does not attach it to any domain. Until a domain mapping pointing at the certificate is + created in Cloud Manager, the certificate is installed but not serving traffic. + +- **Renew with _Overwrite_ to preserve existing bindings.** Renewing or replacing a certificate with _Overwrite_ + enabled updates it **in place** — the Cloud Manager certificate id does not change — so any existing domain + mappings continue to point at the renewed certificate automatically, with no re-mapping required. This is the + recommended renewal workflow. + +- **A brand-new certificate is not automatically adopted by existing domains.** If you enroll a *new* certificate + (a new alias / name) instead of overwriting, existing domain mappings continue to reference the previous + certificate. Re-point the mapping(s) to the new certificate in Cloud Manager before retiring the old one. + (Cloud Manager's own behavior is that when multiple SAN certificates cover the same domain, the most recently + updated/deployed certificate is served for that domain.) + +- **A bound certificate cannot be removed.** A Remove job fails if the target certificate is still referenced by + one or more domain mappings; the failure message lists the mapping(s). Remove or re-point those mappings in + Cloud Manager, then re-run the Remove job. Certificates with no domain mappings delete cleanly (run the pipeline + afterward to fully undeploy). + +> Managing certificate-to-domain bindings from Keyfactor is intentionally out of scope for this release. The Cloud +> Manager domain-mapping APIs support full create/update/delete, so this could be added later (for example, via +> entry parameters) if it becomes a requirement. + +## Certificate Enrollment Alias Requirements + +The alias is the Adobe certificate name and must be unique within the program. Use **Overwrite** to renew or +replace an existing certificate (matched by that name). Certificates created outside Keyfactor that happen to share +a name are surfaced during inventory as `name (id)` so aliases remain unique. diff --git a/docsource/content.md b/docsource/content.md new file mode 100644 index 0000000..e3a9558 --- /dev/null +++ b/docsource/content.md @@ -0,0 +1,62 @@ +## Overview + +The Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension enables Keyfactor Command to +remotely manage customer-managed (OV/EV) TLS/SSL certificates on **Adobe Experience Manager as a Cloud Service** +(AEMaaCS) through the **Adobe Cloud Manager API**. These certificates secure custom domains served by AEMaaCS. +The extension supports inventory, enrollment (add), removal, and discovery. + +In Cloud Manager, certificates are scoped to a **program**, so a certificate store of the `AEMCM` store type +represents a single Cloud Manager program (the store's Store Path is the numeric `programId`), and every +certificate in that program is managed through that one store. + +Two platform caveats are worth calling out up front: Cloud Manager enforces a hard limit of **70 installed +certificates per program** (including Adobe-managed DV certificates and expired certificates) and up to +**100 SANs per certificate**; and Adobe-managed (DV) certificates are **read-only** to this extension, which +manages only customer-managed (OV/EV) certificates. Because of the 70-certificate limit, the extension prefers +updating an existing certificate over creating a new one. + +## Requirements + +### Configure Adobe Cloud Manager API access + +The extension authenticates to the Cloud Manager API with an Adobe IMS **OAuth Server-to-Server** credential +(Adobe has deprecated JWT authentication; it is not used). + +1. In the [Adobe Developer Console](https://developer.adobe.com/console), create (or open) a project and add the + **Cloud Manager API**, choosing the **OAuth Server-to-Server** credential type. +2. Assign the credential a product profile / role with permission to manage Cloud Manager SSL certificates — the + **Business Owner** or **Deployment Manager** role. +3. Record the **Client ID**, **Client Secret**, and **IMS Organization ID**; these are entered on the certificate + store (or discovery job) in Keyfactor Command. + +> :warning: A credential without the **Business Owner** or **Deployment Manager** role can authenticate but cannot +> add, update, or delete certificates. + +### Endpoint access / firewall + +The orchestrator host needs outbound access to: + +- The Keyfactor Command instance +- `ims-na1.adobelogin.com` — Adobe IMS token endpoint (to obtain the bearer access token) +- `cloudmanager.adobe.io` — the Cloud Manager API (inventory, add, remove, and discovery operations) + +### Certificate requirements + +Customer-managed certificates must meet Cloud Manager's requirements. The extension performs best-effort +client-side validation and Cloud Manager enforces the rest server-side: + +- **OV or EV** certificates from a trusted CA. DV and self-signed certificates are not supported for + customer-managed upload. +- Private key in **PKCS#8**, unencrypted. Supported key types: **RSA-2048**, or Elliptic Curve + **secp256r1 (prime256v1)** / **secp384r1**. RSA-3072/4096 are not supported by Cloud Manager. +- Up to **100 SANs** per certificate. + +The extension automatically splits the PKCS#12 supplied by Command into the leaf certificate, the unencrypted +PKCS#8 private key, and the intermediate chain **with the leaf excluded** (Cloud Manager rejects uploads that +include the leaf in the chain). + +## Post Installation + +After installing the extension DLLs on the orchestrator, create the `AEMCM` certificate store type in Keyfactor +Command — with [kfutil](https://github.com/Keyfactor/kfutil) (`kfutil store-types create AEMCM`) or manually from +`integration-manifest.json` — before defining any certificate stores. diff --git a/docsource/images/AEMCM-advanced-store-type-dialog.svg b/docsource/images/AEMCM-advanced-store-type-dialog.svg new file mode 100644 index 0000000..123a979 --- /dev/null +++ b/docsource/images/AEMCM-advanced-store-type-dialog.svg @@ -0,0 +1,67 @@ + + + + + + + + + Edit Certificate Store Type + + + + Basic + Advanced + + Custom Fields + Entry Parameters + + + + + Store Path Type + + + + Freeform + + Fixed + + Multiple Choice + + + + + Other Settings + + Supports Custom Alias + + Forbidden + + Optional + + + Required + Private Key Handling + + Forbidden + + Optional + + + Required + PFX Password Style + + + Default + + Custom + \ No newline at end of file diff --git a/docsource/images/AEMCM-basic-store-type-dialog.svg b/docsource/images/AEMCM-basic-store-type-dialog.svg new file mode 100644 index 0000000..48bf5d0 --- /dev/null +++ b/docsource/images/AEMCM-basic-store-type-dialog.svg @@ -0,0 +1,84 @@ + + + + + + + + + Edit Certificate Store Type + + + + Basic + + Advanced + Custom Fields + Entry Parameters + + + + + Details + + Name + + Adobe Experience Manager Cloud Manager + Short Name + + AEMCM + Custom Capability + + + Custom Capability + + + + Supported Job Types + + + + Inventory + + + Add + + + Remove + + Create + + + Discovery + + ODKG + + + + General Settings + + + + Needs Server + + Blueprint Allowed + + Uses PowerShell + + + + Password Settings + + + Requires Store Password + + Supports Entry Password + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-field-ImsOrgId-dialog.svg b/docsource/images/AEMCM-custom-field-ImsOrgId-dialog.svg new file mode 100644 index 0000000..2fb296b --- /dev/null +++ b/docsource/images/AEMCM-custom-field-ImsOrgId-dialog.svg @@ -0,0 +1,49 @@ + + + + + + + + + Edit Custom Field + × + + + + Basic Information + + Validation Options + + Name + + ImsOrgId + Display Name + + IMS Organization ID + Type + + String + + Default Value + + + Depends On + + + IMS Token Endpoint + + + + CANCEL + + SAVE + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-field-ImsOrgId-validation-options-dialog.svg b/docsource/images/AEMCM-custom-field-ImsOrgId-validation-options-dialog.svg new file mode 100644 index 0000000..7993c23 --- /dev/null +++ b/docsource/images/AEMCM-custom-field-ImsOrgId-validation-options-dialog.svg @@ -0,0 +1,39 @@ + + + + + + + + + Edit Custom Field + × + + + + Basic Information + Validation Options + + + Creating a certificate store + + Optional + + + Required + + Hidden + + + CANCEL + + SAVE + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-field-ImsScopes-dialog.svg b/docsource/images/AEMCM-custom-field-ImsScopes-dialog.svg new file mode 100644 index 0000000..429e882 --- /dev/null +++ b/docsource/images/AEMCM-custom-field-ImsScopes-dialog.svg @@ -0,0 +1,49 @@ + + + + + + + + + Edit Custom Field + × + + + + Basic Information + + Validation Options + + Name + + ImsScopes + Display Name + + IMS Scopes + Type + + String + + Default Value + + openid,AdobeID,read_organizations,additional_info.projectedProductContext + Depends On + + + IMS Organization ID + + + + CANCEL + + SAVE + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-field-ImsScopes-validation-options-dialog.svg b/docsource/images/AEMCM-custom-field-ImsScopes-validation-options-dialog.svg new file mode 100644 index 0000000..7993c23 --- /dev/null +++ b/docsource/images/AEMCM-custom-field-ImsScopes-validation-options-dialog.svg @@ -0,0 +1,39 @@ + + + + + + + + + Edit Custom Field + × + + + + Basic Information + Validation Options + + + Creating a certificate store + + Optional + + + Required + + Hidden + + + CANCEL + + SAVE + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-field-ImsTokenUrl-dialog.svg b/docsource/images/AEMCM-custom-field-ImsTokenUrl-dialog.svg new file mode 100644 index 0000000..25ae406 --- /dev/null +++ b/docsource/images/AEMCM-custom-field-ImsTokenUrl-dialog.svg @@ -0,0 +1,49 @@ + + + + + + + + + Edit Custom Field + × + + + + Basic Information + + Validation Options + + Name + + ImsTokenUrl + Display Name + + IMS Token Endpoint + Type + + String + + Default Value + + https://ims-na1.adobelogin.com/ims/token/v3 + Depends On + + + IMS Organization ID + + + + CANCEL + + SAVE + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-field-ImsTokenUrl-validation-options-dialog.svg b/docsource/images/AEMCM-custom-field-ImsTokenUrl-validation-options-dialog.svg new file mode 100644 index 0000000..7993c23 --- /dev/null +++ b/docsource/images/AEMCM-custom-field-ImsTokenUrl-validation-options-dialog.svg @@ -0,0 +1,39 @@ + + + + + + + + + Edit Custom Field + × + + + + Basic Information + Validation Options + + + Creating a certificate store + + Optional + + + Required + + Hidden + + + CANCEL + + SAVE + \ No newline at end of file diff --git a/docsource/images/AEMCM-custom-fields-store-type-dialog.svg b/docsource/images/AEMCM-custom-fields-store-type-dialog.svg new file mode 100644 index 0000000..1054717 --- /dev/null +++ b/docsource/images/AEMCM-custom-fields-store-type-dialog.svg @@ -0,0 +1,72 @@ + + + + + + + + + Edit Certificate Store Type + + + + Basic + Advanced + Custom Fields + + Entry Parameters + + + + + + ADD + + EDIT + + DELETE + Total: 3 + + + Display Name + Type + Default Value / Options + + + + + + + + + + + IMS Organization ID + String + + + + + + + IMS Token Endpoint + String + https://ims-na1.adobelogin.com/ims/token/v3 + + + + + + + IMS Scopes + String + openid,AdobeID,read_organizations,additional_info.projectedProductContext + \ No newline at end of file diff --git a/integration-manifest.json b/integration-manifest.json index d7031ff..79585de 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -1,18 +1,19 @@ { - "$schema": "https://keyfactor.github.io/integration-manifest-schema.json", + "$schema": "https://keyfactor.github.io/v2/integration-manifest-schema.json", "integration_type": "orchestrator", "name": "Adobe Experience Manager (Cloud Manager) Orchestrator", - "status": "prototype", - "link_github": true, + "status": "production", "update_catalog": false, - "support_level": "kf-community", - "description": "Universal Orchestrator extension for managing customer-managed (OV/EV) TLS/SSL certificates on Adobe Experience Manager as a Cloud Service via the Adobe Cloud Manager API.", + "link_github": true, + "support_level": "kf-supported", "release_dir": "AEMCM.Orchestrator/bin/Release", + "release_project": "AEMCM.Orchestrator/AEMCM.Orchestrator.csproj", + "description": "The Adobe Experience Manager (Cloud Manager) Universal Orchestrator extension manages customer-managed (OV/EV) TLS/SSL certificates on Adobe Experience Manager as a Cloud Service via the Adobe Cloud Manager API, supporting inventory, enrollment, removal, and discovery.", "about": { "orchestrator": { "UOFramework": "10.4", - "pam_support": true, "keyfactor_platform_version": "10.4", + "pam_support": true, "store_types": [ { "Name": "Adobe Experience Manager Cloud Manager", @@ -21,17 +22,18 @@ "ServerRequired": true, "BlueprintAllowed": false, "PowerShell": false, + "LocalStore": false, "PrivateKeyAllowed": "Required", - "SupportsCustomAlias": "Required", "CustomAliasAllowed": "Required", - "StorePathType": "Freeform", + "StorePathType": "", "StorePathValue": "", + "ClientMachineDescription": "The Adobe Cloud Manager API base URL. Enter 'https://cloudmanager.adobe.io'.", + "StorePathDescription": "The numeric Cloud Manager program identifier (programId) that this store manages; for example, '12345'. One store maps to one program.", "SupportedOperations": { "Add": true, "Remove": true, - "Enrollment": false, "Discovery": true, - "Inventory": true + "Enrollment": false }, "PasswordOptions": { "EntrySupported": false, @@ -42,32 +44,36 @@ { "Name": "ImsOrgId", "DisplayName": "IMS Organization ID", - "Type": "Secret", + "Description": "The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential.", + "Type": "String", "DependsOn": "", "DefaultValue": "", "Required": true, - "Description": "Adobe IMS Org ID sent as the x-gw-ims-org-id header." + "IsPAMEligible": false }, { "Name": "ImsTokenUrl", "DisplayName": "IMS Token Endpoint", + "Description": "The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens.", "Type": "String", "DependsOn": "", "DefaultValue": "https://ims-na1.adobelogin.com/ims/token/v3", - "Required": false, - "Description": "Adobe IMS OAuth Server-to-Server token endpoint." + "Required": true, + "IsPAMEligible": false }, { "Name": "ImsScopes", "DisplayName": "IMS Scopes", + "Description": "Comma-separated IMS scopes requested for the access token.", "Type": "String", "DependsOn": "", "DefaultValue": "openid,AdobeID,read_organizations,additional_info.projectedProductContext", - "Required": false, - "Description": "Comma-separated IMS scopes requested for the access token." + "Required": true, + "IsPAMEligible": false } ], - "EntryParameters": [] + "EntryParameters": [], + "JobProperties": [] } ] } diff --git a/scripts/store_types/bash/curl_create_store_types.sh b/scripts/store_types/bash/curl_create_store_types.sh new file mode 100644 index 0000000..50ea656 --- /dev/null +++ b/scripts/store_types/bash/curl_create_store_types.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Store Type creation script using curl +# Generated by Doctool + +set -e + +# Configuration - set these variables before running +KEYFACTOR_HOSTNAME="${KEYFACTOR_HOSTNAME}" +KEYFACTOR_API_PATH="${KEYFACTOR_API_PATH:-KeyfactorAPI}" +KEYFACTOR_AUTH_TOKEN="${KEYFACTOR_AUTH_TOKEN}" + +echo "Creating store type: AEMCM" +curl -s -X POST "https://${KEYFACTOR_HOSTNAME}/${KEYFACTOR_API_PATH}/CertificateStoreTypes" \ + -H "Authorization: Bearer ${KEYFACTOR_AUTH_TOKEN}" \ + -H "Content-Type: application/json" \ + -H "x-keyfactor-requested-with: APIClient" \ + -d '{ + "Name": "Adobe Experience Manager Cloud Manager", + "ShortName": "AEMCM", + "Capability": "AEMCM", + "ServerRequired": true, + "BlueprintAllowed": false, + "PowerShell": false, + "LocalStore": false, + "PrivateKeyAllowed": "Required", + "CustomAliasAllowed": "Required", + "StorePathType": "", + "StorePathValue": "", + "SupportedOperations": { + "Add": true, + "Remove": true, + "Discovery": true, + "Enrollment": false + }, + "PasswordOptions": { + "EntrySupported": false, + "StoreRequired": false, + "Style": "Default" + }, + "Properties": [ + { + "Name": "ImsOrgId", + "DisplayName": "IMS Organization ID", + "Description": "The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential.", + "Type": "String", + "DependsOn": "", + "DefaultValue": "", + "Required": true, + "IsPAMEligible": false + }, + { + "Name": "ImsTokenUrl", + "DisplayName": "IMS Token Endpoint", + "Description": "The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens.", + "Type": "String", + "DependsOn": "", + "DefaultValue": "https://ims-na1.adobelogin.com/ims/token/v3", + "Required": true, + "IsPAMEligible": false + }, + { + "Name": "ImsScopes", + "DisplayName": "IMS Scopes", + "Description": "Comma-separated IMS scopes requested for the access token.", + "Type": "String", + "DependsOn": "", + "DefaultValue": "openid,AdobeID,read_organizations,additional_info.projectedProductContext", + "Required": true, + "IsPAMEligible": false + } + ], + "EntryParameters": [], + "JobProperties": [] +}' + diff --git a/scripts/store_types/bash/kfutil_create_store_types.sh b/scripts/store_types/bash/kfutil_create_store_types.sh new file mode 100644 index 0000000..770b73c --- /dev/null +++ b/scripts/store_types/bash/kfutil_create_store_types.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Store Type creation script using kfutil +# Generated by Doctool + +set -e + +echo "Creating store type: AEMCM" +kfutil store-types create AEMCM + diff --git a/scripts/store_types/powershell/kfutil_create_store_types.ps1 b/scripts/store_types/powershell/kfutil_create_store_types.ps1 new file mode 100644 index 0000000..4bfd92b --- /dev/null +++ b/scripts/store_types/powershell/kfutil_create_store_types.ps1 @@ -0,0 +1,6 @@ +# Store Type creation script using kfutil +# Generated by Doctool + +Write-Host "Creating store type: AEMCM" +kfutil store-types create AEMCM + diff --git a/scripts/store_types/powershell/restmethod_create_store_types.ps1 b/scripts/store_types/powershell/restmethod_create_store_types.ps1 new file mode 100644 index 0000000..a33f7ce --- /dev/null +++ b/scripts/store_types/powershell/restmethod_create_store_types.ps1 @@ -0,0 +1,78 @@ +# Store Type creation script using Invoke-RestMethod +# Generated by Doctool + +# Configuration - set these variables before running +$KeyfactorHostname = $env:KEYFACTOR_HOSTNAME +$KeyfactorApiPath = if ($env:KEYFACTOR_API_PATH) { $env:KEYFACTOR_API_PATH } else { "KeyfactorAPI" } +$KeyfactorAuthToken = $env:KEYFACTOR_AUTH_TOKEN + +$Headers = @{ + "Authorization" = "Bearer $KeyfactorAuthToken" + "Content-Type" = "application/json" + "x-keyfactor-requested-with" = "APIClient" +} + +Write-Host "Creating store type: AEMCM" +$Body = @' +{ + "Name": "Adobe Experience Manager Cloud Manager", + "ShortName": "AEMCM", + "Capability": "AEMCM", + "ServerRequired": true, + "BlueprintAllowed": false, + "PowerShell": false, + "LocalStore": false, + "PrivateKeyAllowed": "Required", + "CustomAliasAllowed": "Required", + "StorePathType": "", + "StorePathValue": "", + "SupportedOperations": { + "Add": true, + "Remove": true, + "Discovery": true, + "Enrollment": false + }, + "PasswordOptions": { + "EntrySupported": false, + "StoreRequired": false, + "Style": "Default" + }, + "Properties": [ + { + "Name": "ImsOrgId", + "DisplayName": "IMS Organization ID", + "Description": "The Adobe IMS Organization ID (e.g. 'XXXXXXXX@AdobeOrg'), sent as the 'x-gw-ims-org-id' header on Cloud Manager API requests. This is an identifier, not a credential.", + "Type": "String", + "DependsOn": "", + "DefaultValue": "", + "Required": true, + "IsPAMEligible": false + }, + { + "Name": "ImsTokenUrl", + "DisplayName": "IMS Token Endpoint", + "Description": "The Adobe IMS OAuth Server-to-Server token endpoint used to obtain access tokens.", + "Type": "String", + "DependsOn": "", + "DefaultValue": "https://ims-na1.adobelogin.com/ims/token/v3", + "Required": true, + "IsPAMEligible": false + }, + { + "Name": "ImsScopes", + "DisplayName": "IMS Scopes", + "Description": "Comma-separated IMS scopes requested for the access token.", + "Type": "String", + "DependsOn": "", + "DefaultValue": "openid,AdobeID,read_organizations,additional_info.projectedProductContext", + "Required": true, + "IsPAMEligible": false + } + ], + "EntryParameters": [], + "JobProperties": [] +} +'@ + +Invoke-RestMethod -Uri "https://$KeyfactorHostname/$KeyfactorApiPath/CertificateStoreTypes" -Method POST -Headers $Headers -Body $Body +