├── .github ├── .markdown-link-check.json ├── .markdownlint.yml ├── CODEOWNERS ├── settings.yml └── workflows │ ├── markdown-analysis.yml │ └── milestone.yaml ├── .gitignore ├── .gitvote.yml ├── CONTRIBUTING.md ├── LICENSE ├── LICENSES └── Apache-2.0.txt ├── README.md ├── REUSE.toml ├── doc ├── 01-model │ ├── 01-model.md │ ├── 02-elements-toplevel.md │ ├── 03-elements-sub.md │ ├── 04-example.md │ ├── 06-conventions.md │ ├── 07-extensions.md │ ├── README.md │ ├── ocm-helm-indirect.png │ ├── ocm-helm-simple.png │ ├── ocmidentity.png │ └── ocmresourceaccess.png ├── 02-processing │ ├── 01-references.md │ ├── 02-signing.md │ ├── 03-signing-process.md │ ├── 04-signing-examples.md │ ├── 05-component-descriptor-normalization.md │ ├── 06-artifact-normalization.md │ └── README.md ├── 03-persistence │ ├── 01-operations.md │ ├── 02-mappings.md │ ├── README.md │ └── ocm2oci-mapping.png ├── 04-extensions │ ├── 00-component-descriptor │ │ ├── README.md │ │ ├── v2.md │ │ └── v3.md │ ├── 01-artifact-types │ │ ├── README.md │ │ ├── blob.md │ │ ├── blueprint.md │ │ ├── executable.md │ │ ├── file-system.md │ │ ├── gitops.md │ │ ├── helmchart.md │ │ ├── npm.md │ │ ├── oci-artifact.md │ │ ├── oci-image.md │ │ ├── sbom.md │ │ ├── template.md │ │ ├── toiexecutor.md │ │ └── toipackage.md │ ├── 02-access-types │ │ ├── README.md │ │ ├── github.md │ │ ├── helm.md │ │ ├── localblob.md │ │ ├── npm.md │ │ ├── ociartifact.md │ │ ├── ociblob.md │ │ ├── s3.md │ │ └── wget.md │ ├── 03-storage-backends │ │ ├── README.md │ │ ├── component-archive.md │ │ ├── ctf.md │ │ ├── oci.md │ │ ├── ocm2oci-mapping.png │ │ ├── ocmembedding.png │ │ └── s3.md │ ├── 04-algorithms │ │ ├── README.md │ │ ├── artifact-normalization-types.md │ │ ├── component-descriptor-normalization-algorithms.md │ │ ├── digest-algorithms.md │ │ ├── label-merge-algorithms.md │ │ └── signing-algorithms.md │ ├── README.md │ └── common │ │ └── formatspec.md ├── 05-guidelines │ ├── 01-transport.md │ ├── 02-contract.md │ ├── 03-references.md │ └── README.md ├── OCM-Ecosystem.png ├── OCM-Implementation-Model.pptx └── glossary.md ├── metadata.yaml └── scripts ├── requirements.txt └── toc_gen.py /.github/.markdown-link-check.json: -------------------------------------------------------------------------------- 1 | { 2 | "replacementPatterns": [ 3 | { 4 | "pattern": "^/", 5 | "replacement": "/github/workspace/" 6 | } 7 | ], 8 | "ignorePatterns": [ 9 | { 10 | "pattern": "^http[s]*://localhost.*" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.github/.markdownlint.yml: -------------------------------------------------------------------------------- 1 | default: true 2 | 3 | MD013: false #https://github.com/DavidAnson/markdownlint/blob/HEAD/doc/Rules.md#md013 4 | MD029: false #https://github.com/DavidAnson/markdownlint/blob/HEAD/doc/Rules.md#md033 5 | MD033: false #https://github.com/DavidAnson/markdownlint/blob/HEAD/doc/Rules.md#md033 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Default owners for everything in the repo. 2 | # Unless a later match takes precedence, the Maintainers team 3 | # will be requested for review when someone opens a pull request. 4 | * @open-component-model/Maintainers 5 | 6 | # Changes on repository settings require admin permissions 7 | /.github/settings.yml @open-component-model/admins 8 | /.github/CODEOWNERS @open-component-model/admins 9 | 10 | # Owners for specific directories 11 | #/docs/ @/ 12 | #/src/ @/ 13 | 14 | # Owners for specific file types 15 | #*.md @/ 16 | #*.go @/ 17 | 18 | # Individual users as owners, e.g. a lead maintainer for a specific component: 19 | # /src/critical-component/ @lead-maintainer-username 20 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # These settings are synced to GitHub by https://probot.github.io/apps/settings/ 2 | 3 | # see: https://github.com/open-component-model/.github/blob/main/.github/settings.yml 4 | _extends: .github 5 | 6 | labels: 7 | - name: repo/ocm-spec 8 | color: bfd4f2 9 | -------------------------------------------------------------------------------- /.github/workflows/markdown-analysis.yml: -------------------------------------------------------------------------------- 1 | name: markdown-analysis-workflow 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | paths: 11 | - '**/*.md' 12 | 13 | jobs: 14 | markdown-analysis-job: 15 | runs-on: ubuntu-latest 16 | name: 'github actions: markdownlint' 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | - name: markdownlint 21 | uses: nosborn/github-action-markdown-cli@v1.1.1 22 | with: 23 | files: . 24 | config_file: ./.github/.markdownlint.yml 25 | - name: markdown link check 26 | uses: gaurav-nelson/github-action-markdown-link-check@v1 27 | with: 28 | config-file: ./.github/.markdown-link-check.json 29 | -------------------------------------------------------------------------------- /.github/workflows/milestone.yaml: -------------------------------------------------------------------------------- 1 | name: Set milestone 2 | on: 3 | issues: 4 | types: 5 | - closed 6 | pull_request: 7 | types: 8 | - closed 9 | 10 | jobs: 11 | set_milestone: 12 | uses: open-component-model/.github/.github/workflows/milestone.yml@main 13 | secrets: inherit 14 | permissions: 15 | issues: write 16 | pull-requests: write 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .sw[pq] 2 | /local 3 | /tmp 4 | .idea 5 | .vscode 6 | **/__index__.md* 7 | /scripts/test 8 | /.project 9 | -------------------------------------------------------------------------------- /.gitvote.yml: -------------------------------------------------------------------------------- 1 | # GitVote configuration file 2 | # 3 | # GitVote will look for it in the following locations (in order of precedence): 4 | # 5 | # - At the root of the repository where the vote was created 6 | # - At the root of the .github repository, for organization wide configuration 7 | # 8 | 9 | # Automation (optional) 10 | # 11 | # Create votes automatically on PRs when any of the files affected by the PR 12 | # match any of the patterns provided. Patterns must follow the gitignore 13 | # format (https://git-scm.com/docs/gitignore#_pattern_format). 14 | # 15 | # Each automation rule must include a list of patterns and the profile to use 16 | # when creating the vote. This allows creating votes automatically using the 17 | # desired configuration based on the patterns matched. Rules are processed in 18 | # the order provided, and the first match wins. 19 | # 20 | # automation: 21 | # enabled: true 22 | # rules: 23 | # - patterns: 24 | # - "README.md" 25 | # - "*.txt" 26 | # profile: default 27 | # 28 | automation: 29 | enabled: false 30 | rules: 31 | - patterns: [] 32 | profile: profile1 33 | 34 | # Configuration profiles (required) 35 | # 36 | # A configuration profile defines some properties of a vote, like its duration, 37 | # the pass threshold or the users who have a binding vote. It's possible to 38 | # define multiple configuration profiles, each with a different set of settings. 39 | # 40 | profiles: 41 | # Default configuration profile 42 | # 43 | # This profile will be used with votes created with the /vote command 44 | default: 45 | # Voting duration (required) 46 | # 47 | # How long the vote will be open 48 | # 49 | # Units supported (can be combined as in 1hour 30mins): 50 | # 51 | # minutes | minute | mins | min | m 52 | # hours | hour | hrs | hrs | h 53 | # days | day | d 54 | # weeks | week | w 55 | # 56 | duration: 5d 57 | 58 | # Pass threshold (required) 59 | # 60 | # Percentage of votes in favor required to pass the vote 61 | # 62 | # The percentage is calculated based on the number of votes in favor and the 63 | # number of allowed voters (see allowed_voters field below for more details). 64 | pass_threshold: 50 65 | 66 | # Allowed voters (optional) 67 | # 68 | # List of GitHub teams and users who have binding votes 69 | # 70 | # If no teams or users are provided, all repository collaborators will be 71 | # allowed to vote. For organization-owned repositories, the list of 72 | # collaborators includes outside collaborators, organization members that 73 | # are direct collaborators, organization members with access through team 74 | # memberships, organization members with access through default organization 75 | # permissions, and organization owners. 76 | # 77 | # By default, teams' members with the maintainer role are allowed to vote 78 | # as well. By using the `exclude_team_maintainers` option, it's possible to 79 | # modify this behavior so that only teams' members with the member role are 80 | # considered allowed voters. Please note that this option only applies to 81 | # the teams explicitly listed in `allowed_voters/teams`. 82 | # 83 | # Teams names must be provided without the organization prefix. 84 | # 85 | # allowed_voters: 86 | # teams: 87 | # - team1 88 | # users: 89 | # - cynthia-sg 90 | # - tegioz 91 | # exclude_team_maintainers: false 92 | # 93 | allowed_voters: 94 | teams: 95 | - Maintainers 96 | users: [] 97 | 98 | # Periodic status check 99 | #  100 | # GitVote allows checking the status of a vote in progress manually by 101 | # calling the /check-vote command. The periodic status check option makes 102 | # it possible to automate the execution of status checks periodically. The 103 | # vote status will be published to the corresponding issue or pull request, 104 | # the same way as if the /check-vote command would have been called 105 | # manually. 106 | # 107 | # When this option is enabled, while the vote is open, a status check will 108 | # be run automatically using the frequency configured. Please note that the 109 | # hard limit of one status check per day still applies, so if the command 110 | # has been called manually the automatic periodic run may be delayed. 111 | # Automatic status checks won't be run if the vote will be closed within 112 | # the next hour. 113 | # 114 | # Units supported: 115 | # 116 | # - day / days 117 | # - week / weeks 118 | # 119 | # As an example, using a value of "5 days" would mean that 5 days after the 120 | # vote was created, and every 5 days after that, an automatic status check 121 | # will be run. 122 | # 123 | # periodic_status_check: "5 days" 124 | # 125 | #periodic_status_check: null 126 | periodic_status_check: 5m 127 | 128 | # Close on passing 129 | #  130 | # By default, votes remain open for the configured duration. Sometimes, 131 | # specially on votes that stay open for a long time, it may be preferable 132 | # to close a vote automatically once the passing threshold has been met. 133 | # The close on passing feature makes this possible. Open votes where this 134 | # feature has been enabled will be checked once daily and, if GitVote 135 | # detects that the vote has passed, it will automatically close it. 136 | #  137 | # close_on_passing: true 138 | # 139 | close_on_passing: false 140 | 141 | # Additional configuration profiles 142 | # 143 | # In addition to the default configuration profile, it is possible to add more 144 | # to easily create votes with different settings. To create a vote that uses a 145 | # different profile you can use the command /vote-PROFILE. In the case below, 146 | # the command would be /vote-profile1 147 | # 148 | # Please note that each profile must contain all required fields. The default 149 | # profile is used when using the /vote command, but its values are not used as 150 | # default values when they are not provided on other profiles. 151 | # 152 | profileocm: 153 | duration: 5d 154 | pass_threshold: 50 155 | allowed_voters: 156 | teams: 157 | - Maintainers 158 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to the OCM community 2 | 3 | We welcome many different types of contributions. 4 | 5 | Please refer to the [Contributing Guide in the Community repository](https://github.com/open-component-model/community/blob/main/CONTRIBUTING.md) for more information on how to get support from maintainers, find work to contribute, the Pull Request checklist, the Pull Request process, and other useful information on contributing to the OCM projects. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | 37 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 38 | 39 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | 41 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 42 | 43 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | 57 | APPENDIX: How to apply the Apache License to your work. 58 | 59 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 60 | 61 | Copyright [yyyy] [name of copyright owner] 62 | 63 | Licensed under the Apache License, Version 2.0 (the "License"); 64 | you may not use this file except in compliance with the License. 65 | You may obtain a copy of the License at 66 | 67 | http://www.apache.org/licenses/LICENSE-2.0 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Component Model (OCM) 2 | 3 | [![REUSE status](https://api.reuse.software/badge/github.com/open-component-model/ocm-spec)](https://api.reuse.software/info/github.com/open-component-model/ocm-spec) 4 | 5 | The _Open Component Model (OCM)_ is an open standard to describe software-bill-of-deliveries (SBOD). OCM is a technology-agnostic and machine-readable format focused on the software artifacts that must be delivered for software products. OCM provides a globally unique identity scheme which can be used to identify components and artifacts throughout the entire software lifecycle management process,... 6 | 7 | Its focus is describing versioned sets of artifacts and to assign globally unique identities. OCM makes those artifacts queryable: what is inside, where is it from, is it authentic, etc. But it does not deal with building those artifacts or how to deploy them. Such tasks are left to tools on top of the model. In this way, they are able to access the artifact by its identity. Different tools may keep their own metadata bound together by the identities provided by the model. 8 | 9 | OCM provides a common language usable by tools to talk about software artifacts, regardless of the technologies and the processes working on them. Tool specific metadata, like deployment descriptions, are handled as own, typed artifacts. This enables the provisioning of content-agnostic tools: for example, transporting software between environments, signing and verification, providing compliance data, etc. 10 | 11 | ![OCM Overview](doc/OCM-Ecosystem.png) 12 | 13 | The following chapters provide a formal description of the format to describe software artifacts and a storage layer to persist those and make them available from remote. 14 | 15 | ## Specification 16 | 17 | ### Core Parts 18 | 19 | * 1. [Model](doc/01-model/README.md) 20 | * 1.1 [OCM Model](doc/01-model/01-model.md#ocm-model) 21 | * 1.1.1 [Introduction](doc/01-model/01-model.md#introduction) 22 | * 1.1.2 [Components and Component Versions](doc/01-model/01-model.md#components-and-component-versions) 23 | * 1.1.3 [Component Repositories](doc/01-model/01-model.md#component-repositories) 24 | * 1.1.4 [Summary](doc/01-model/01-model.md#summary) 25 | * 1.2. [Model Elements](doc/01-model/02-elements-toplevel.md#model-elements) 26 | * 1.2.1 [Components and Component Versions](doc/01-model/02-elements-toplevel.md#components-and-component-versions) 27 | * 1.2.2 [Artifacts (Resources and Sources)](doc/01-model/02-elements-toplevel.md#artifacts-resources-and-sources) 28 | * 1.2.3 [Sources](doc/01-model/02-elements-toplevel.md#sources) 29 | * 1.2.4 [Resources](doc/01-model/02-elements-toplevel.md#resources) 30 | * 1.2.5 [References](doc/01-model/02-elements-toplevel.md#references) 31 | * 1.2.6 [Summary](doc/01-model/02-elements-toplevel.md#summary) 32 | * 1.3. [Model Elements - Fundamentals](doc/01-model/03-elements-sub.md) 33 | * 1.3.1 [Identifiers](doc/01-model/03-elements-sub.md#identifiers) 34 | * 1.3.2 [Access Specification](doc/01-model/03-elements-sub.md#access-specification) 35 | * 1.3.3 [Access Types](doc/01-model/03-elements-sub.md#access-types) 36 | * 1.3.4 [Labels](doc/01-model/03-elements-sub.md#labels) 37 | * 1.3.5 [Repository Contexts](doc/01-model/03-elements-sub.md#repository-contexts) 38 | * 1.3.6 [Signatures](doc/01-model/03-elements-sub.md#signatures) 39 | * 1.3.7 [Digest Info](doc/01-model/03-elements-sub.md#digest-info) 40 | * 1.3.8 [Signature Info](doc/01-model/03-elements-sub.md#signature-info) 41 | * 1.4 [Example of a complete Component Version](doc/01-model/04-example.md#example-of-a-complete-component-version) 42 | * 1.5 [Conventions](doc/01-model/06-conventions.md#conventions) 43 | * 1.5.1 [Intended Environments](doc/01-model/06-conventions.md#intended-environments) 44 | * 1.5.2 [Selection of Usage Scenarios](doc/01-model/06-conventions.md#selection-of-usage-scenarios) 45 | * 1.6 [Extending the Open Component Model](doc/01-model/07-extensions.md#extending-the-open-component-model) 46 | * 1.6.1 [Functional extensions](doc/01-model/07-extensions.md#functional-extensions) 47 | * 1.6.2 [Semantic extensions](doc/01-model/07-extensions.md#semantic-extensions) 48 | * 2. [Processing](doc/02-processing/README.md) 49 | * 2.1 [Referencing](doc/02-processing/01-references.md#referencing) 50 | * 2.1.1 [Example](doc/02-processing/01-references.md#example) 51 | * 2.2 [Signing](doc/02-processing/02-signing.md#signing) 52 | * 2.2.1 [Verification Procedure](doc/02-processing/02-signing.md#verification-procedure) 53 | * 2.3 [Normalization](doc/02-processing/03-signing-process.md#signing-process-and-normalization) 54 | * 2.3.1 [Artifact Digest](doc/02-processing/03-signing-process.md#determing-the-artifact-digests) 55 | * 2.3.2 [Normalization Types](doc/02-processing/03-signing-process.md#normalization-types) 56 | * 2.3.3 [Serialization Format](doc/02-processing/03-signing-process.md#serialization-format) 57 | * 2.3.4 [Recursive Digest Calculation](doc/02-processing/03-signing-process.md#recursive-digest-calculation) 58 | * 2.4 [Example](doc/02-processing/04-signing-examples.md#examples-for-signing-of-component-version) 59 | * 2.4.1 [Simple Component-Version](doc/02-processing/04-signing-examples.md#simple-component-version) 60 | * 2.4.2 [Component-Version With Reference](doc/02-processing/04-signing-examples.md#component-version-with-reference) 61 | * 2.5 [Component Descriptor Normalization](doc/02-processing/04-signing-examples.md#component-descriptor-normalization) 62 | * 2.5.1 [Signing-relevant information in Component Descriptors](doc/02-processing/04-signing-examples.md#relevant-information-in-component-descriptors) 63 | * 2.5.2 [Exclude Resources from Normalization/Signing](doc/02-processing/05-component-descriptor-normalization.md#exclude-resources-from-normalizationsigning) 64 | * 2.5.3 [Generic Normalization Format](doc/02-processing/05-component-descriptor-normalization.md#generic-normalization-format) 65 | * 2.6 [Artifact Normalization](doc/02-processing/06-artifact-normalization.md#artifact-normalization) 66 | * 2.6.1 [Blob Representation Format for Resource Types](doc/02-processing/06-artifact-normalization.md#blob-representation-format-for-resource-types) 67 | * 2.6.2 [Interaction of Local Blobs, Access Methods, Uploaders and Media Types](doc/02-processing/06-artifact-normalization.md#interaction-of-local-blobs-access-methods-uploaders-and-media-types) 68 | * 3. [Persistence](doc/03-persistence/README.md) 69 | * 3.1 [Model Operations](doc/03-persistence/01-operations.md#model-operations) 70 | * 3.2 [Abstract Operations defined by the Open Component Model](doc/03-persistence/01-operations.md#abstract-operations-defined-by-the-open-component-model) 71 | * 3.2.1 [Repository Operations](doc/03-persistence/01-operations.md#repository-operations) 72 | * 3.2.2 [Access Method Operations](doc/03-persistence/01-operations.md#access-method-operations) 73 | * 3.3. [Mappings for OCM Persistence](doc/03-persistence/02-mappings.md#mappings-for-ocm-persistence) 74 | * 3.3.1 [Storage Backend Mappings for the Open Component Model](doc/03-persistence/02-mappings.md#storage-backend-mappings-for-the-open-component-model) 75 | 76 | ### Extensible Parts 77 | 78 | * 4 [Extensions](doc/04-extensions/README.md) 79 | * 4.1 [Artifact Types](doc/04-extensions/01-artifact-types/README.md) 80 | * 4.1.1 [blob](doc/04-extensions/01-artifact-types/blob.md) 81 | * 4.1.2 [directoryTree, fileSystem](doc/04-extensions/01-artifact-types/file-system.md) 82 | * 4.1.3 [gitOpsTemplate](doc/04-extensions/01-artifact-types/gitops.md) 83 | * 4.1.4 [helmChart](doc/04-extensions/01-artifact-types/helmchart.md) 84 | * 4.1.5 [npmPackage](doc/04-extensions/01-artifact-types/npm.md) 85 | * 4.1.6 [ociArtifact](doc/04-extensions/01-artifact-types/oci-artifact.md) 86 | * 4.1.7 [ociImage](doc/04-extensions/01-artifact-types/oci-image.md) 87 | * 4.1.8 [executable](doc/04-extensions/01-artifact-types/executable.md) 88 | * 4.1.9 [sbom](doc/04-extensions/01-artifact-types/sbom.md) 89 | * 4.2 [Access Method Types](doc/04-extensions/02-access-types/README.md) 90 | * 4.2.1 [localBlob](doc/04-extensions/02-access-types/localblob.md) 91 | * 4.2.2 [ociArtifact](doc/04-extensions/02-access-types/ociartifact.md) 92 | * 4.2.3 [ociBlob](doc/04-extensions/02-access-types/ociblob.md) 93 | * 4.2.4 [helm](doc/04-extensions/02-access-types/helm.md) 94 | * 4.2.5 [gitHub](doc/04-extensions/02-access-types/github.md) 95 | * 4.2.6 [s3](doc/04-extensions/02-access-types/s3.md) 96 | * 4.2.7 [npm](doc/04-extensions/02-access-types/npm.md) 97 | * 4.2.8 [wget](doc/04-extensions/02-access-types/wget.md) 98 | * 4.3 [Storage Backend Mappings](doc/04-extensions/03-storage-backends/README.md) 99 | * 4.3.1 [OCIRegistry](doc/04-extensions/03-storage-backends/oci.md) 100 | * 4.3.2 [FileSystem (CTF)](doc/04-extensions/03-storage-backends/ctf.md) 101 | * 4.3.3 [FileSystem (Component Archive)](doc/04-extensions/03-storage-backends/component-archive.md) 102 | * 4.3.4 [AWS S3](doc/04-extensions/03-storage-backends/s3.md) 103 | * 4.4 [Algorithms](doc/04-extensions/04-algorithms/README.md) 104 | * 4.4.1 [Artifact Normalization](doc/04-extensions/04-algorithms/artifact-normalization-types.md) 105 | * 4.4.2 [Digest Algorithms](doc/04-extensions/04-algorithms/label-merge-algorithms.md) 106 | * 4.4.3 [Label Merge Algorithm](doc/04-extensions/04-algorithms/digest-algorithms.md) 107 | * 4.4.4 [Component Descriptor Normalization Algorithms](doc/04-extensions/04-algorithms/component-descriptor-normalization-algorithms.md) 108 | * 4.4.5 [Signing Algorithms](doc/04-extensions/04-algorithms/signing-algorithms.md) 109 | 110 | ### Guidelines and Conventions 111 | 112 | * 5. [Guidelines](doc/05-guidelines/README.md) 113 | * 5.1 [Transport](doc/05-guidelines/01-transport.md#transport) 114 | * 5.1.1 [Kinds of Transports](doc/05-guidelines/01-transport.md#kinds-of-transports) 115 | * 5.2 [Model Contract](doc/05-guidelines/02-contract.md#model-contract) 116 | * 5.2.1 [Example: Helm deployment](doc/05-guidelines/02-contract.md#example-helm-deployment) 117 | * 5.3 [References](doc/05-guidelines/03-references.md#references) 118 | * 5.3.1 [Relative Artifact References](doc/05-guidelines/03-references.md#relative-artifact-references) 119 | * 5.3.2 [Absolute Artifact References](doc/05-guidelines/03-references.md#absolute-artifact-references) 120 | 121 | ### Glossary 122 | 123 | * 6. [Glossary](doc/glossary.md) 124 | 125 | ## Central OCM project web page 126 | 127 | Check out the main project [web page](https://ocm.software) to find out more about OCM. It is your central entry point to all kinds of ocm related [docs and guides](https://ocm.software/docs/getting-started), this [spec](https://ocm.software/docs/overview/specification/) and all project-related [github repositories](https://github.com/open-component-model). It also offers a [Getting Started](https://ocm.software/docs/getting-started) to quickly make your hands dirty with ocm, its toolset and concepts :-) 128 | 129 | ## Contributing 130 | 131 | Code contributions, feature requests, bug reports, and help requests are very welcome. Please refer to the [Contributing Guide in the Community repository](https://github.com/open-component-model/community/blob/main/CONTRIBUTING.md) for more information on how to contribute to OCM. 132 | 133 | OCM follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). 134 | 135 | ## Licensing 136 | 137 | Copyright 2022 SAP SE or an SAP affiliate company and Open Component Model contributors. 138 | Please see our [LICENSE](LICENSE) for copyright and license information. 139 | Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/open-component-model/ocm-spec). 140 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | SPDX-PackageName = "ocm-spec" 3 | SPDX-PackageSupplier = "ospo@sap.com" 4 | SPDX-PackageDownloadLocation = "https://github.com/open-component-model/ocm-spec" 5 | SPDX-PackageComment = "The code in this project may include calls to APIs (\"API Calls\") of\n SAP or third-party products or services developed outside of this project\n (\"External Products\").\n \"APIs\" means application programming interfaces, as well as their respective\n specifications and implementing code that allows software to communicate with\n other software.\n API Calls to External Products are not licensed under the open source license\n that governs this project. The use of such API Calls and related External\n Products are subject to applicable additional agreements with the relevant\n provider of the External Products. In no event shall the open source license\n that governs this project grant any rights in or to any External Products, or\n alter, expand or supersede any terms of the applicable additional agreements.\n If you have a valid license agreement with SAP for the use of a particular SAP\n External Product, then you may make use of any API Calls included in this\n project's code for that SAP External Product, subject to the terms of such\n license agreement. If you do not have a valid license agreement for the use of\n a particular SAP External Product, then you may only make use of any API Calls\n in this project for that SAP External Product for your internal, non-productive\n and non-commercial test and evaluation of such API Calls. Nothing herein grants\n you any rights to use or access any SAP External Product, or provide any third\n parties the right to use of access any SAP External Product, through API Calls." 6 | 7 | [[annotations]] 8 | path = "**" 9 | precedence = "aggregate" 10 | SPDX-FileCopyrightText = "2025 SAP SE or an SAP affiliate company and Open Component Model contributors" 11 | SPDX-License-Identifier = "Apache-2.0" 12 | -------------------------------------------------------------------------------- /doc/01-model/01-model.md: -------------------------------------------------------------------------------- 1 | # OCM Model 2 | 3 | This chapter describes the elements and data formats the Open Component Model deals with. All implementations MUST provide a binding for those kinds of elements. 4 | 5 | ## Introduction 6 | 7 | The Open Compoment Model consists of a core model plus extensions. The core model describes the key elements *Component*, *Component Version* being stored in *Component Registries*. *Component Versions* have a type and an identity, and consist of *sources*, *resources* and *references*. *Component Registries* are containers persisting component versions and may exist in various types for different storage technologies. Many parts of the Open-Component-Model can be extended to provide flexibility and adaption to different environments. Some of these extension are defined in this specification. Others may be defined customer-specific or for dedicated environments. 8 | 9 | The following chapters will provide more details about these concepts. 10 | 11 | ## Components and Component Versions 12 | 13 | Usually, complex software products are divided into logical units (called components in this specification). A component is typically maintained in a version control system. It has a build procedure generating binary artifacts from source code and a release process to make it available for consumers. Usually, releases are repeated from time to time, making new versions available. A component is a logical unit within a software product. It is a semantic bracket around software pieces belonging together because they fulfill a specific purpose. E.g. like, "This is the Frontend Component," "This is the Database component," and "This is the Kubernetes vertical autoscale component." 14 | 15 | In the Open Component Model, a *Component Version* is described by a *Component Descriptor*. It describes the resources, sources, and aggregated other Component Versions belonging to a particular Component Version. A Component Descriptor is stored in a yaml file following this [schema](https://github.com/open-component-model/ocm/blob/main/resources/component-descriptor-ocm-v3-schema.yaml). 16 | 17 | A component itself is described by a globally unique identity. Each component version is described by the identity of the component plus a version number following the [semantic versioning](https://semver.org) specification. 18 | 19 | Example: 20 | 21 | ```yaml 22 | ... 23 | component: 24 | name: github.com/open-component-model/echoserver # name of this component 25 | version: 0.1.0 # version of this component 26 | provider: # provider of this component 27 | name: open-component-model 28 | ``` 29 | 30 | A component version contains all artifacts required for using it, plus additional metadata. Such artifacts in OCM are called resources. Resources are usually built or packaged from something, e.g., code in a git repo. The artifacts needed for creating a component version are named *sources* in OCM. 31 | 32 | ```yaml 33 | ... 34 | component: 35 | name: ... 36 | ... 37 | resources: # -> resources making this component 38 | - name: image # -> name of this resource 39 | version: "1.0" # -> version of this resource 40 | type: ociImage # -> type of the resource (here indicating a container image) 41 | relation: external # -> resource is provided by a different entity than the component 42 | sources: # -> information about the origin (source code) of this component 43 | - name: echoserver_source # -> name of the source 44 | version: 0.1.0 # -> version of this source 45 | type: git # -> type of the source (here Git repository) 46 | ``` 47 | 48 | A component version does not consist only of identities but also carries access information for the technical content behind an artifact. Therefore, given the access to a component descriptor also provides access to the content of the described artifacts (e.g. how to find an OCI image built from a Dockerfile). 49 | 50 | ```yaml 51 | ... 52 | component: 53 | name: ... 54 | ... 55 | resources: 56 | - name: ... 57 | ... 58 | access: # -> access information how to locate this resource 59 | imageReference: gcr.io/google_containers/echoserver:1.10 60 | type: ociArtifact 61 | sources: 62 | - name: ... 63 | ... 64 | access: # -> access information how to locate this resource 65 | commit: 9b2cf6ced322c7b938533caa22d5a5f48105b3ab 66 | ref: refs/heads/main 67 | repoUrl: github.com/open-component-model/ocm 68 | type: github 69 | ``` 70 | 71 | A *Component Version* can also reference other *Component Versions* using their identity. In this way aggregations of components are possible. OCM does not make any assumption of the meaning of the reference. Often you will see component versions containing only references and no sources or resources. They can be used for example to describe deployments or delivery packages of software. 72 | 73 | Example: 74 | 75 | ```yaml 76 | ... 77 | component: 78 | name: ... 79 | ... 80 | componentReferences: # -> components referenced by this component 81 | - name: installer # -> name of reference in this component descriptor 82 | componentName: github.com/mandelsoft/ocmhelminstaller # -> name of referenced component 83 | version: 0.1.0 # -> version of referenced component 84 | ``` 85 | 86 | ## Component Repositories 87 | 88 | The definition of a component descriptor is not enough to provide standardized remote access for component versions and allow referencing between component versions. Therefore a *Component Repository* is the second important entity in the Open Component Model. 89 | 90 | The component repository acts as the access point to the elements of the component model. The OCM specification does not define an access protocol but instead uses existing storage technologies and their protocol and defines a mapping from OCM elements to storage elements. The most prominent example is an [OCI registry](https://github.com/opencontainers/distribution-spec/blob/main/spec.md). Other technologies are object stores like Amazon S3 or file systems. File systems do not provide remote access but are helpful for offline scenarios and transporting component versions between locations. 91 | 92 | A component descriptor contains references to all other elements belonging to a component version. Those elements may be stored in the same repository or in other storages. Blob content may be stored along with the component descriptor as a special case. Those blobs are called local blobs. 93 | 94 | All repositories that can be used to store content according to the Open Component Model, need to be described by a specification. 95 | 96 | Such a specification is usable by a language binding to gain access to this repository. 97 | In a concrete environment all those repositories are usable, for which an 98 | implementation of the [abstract model operations](../03-persistence/01-operations.md) exists. 99 | 100 | A repository specification has a type, the *Repository Type* 101 | used to identify the required [mapping](../03-persistence/02-mappings.md) 102 | and the information required to identity a concrete repository instance. 103 | 104 | ## Summary 105 | 106 | Component Versions are the central concept of OCM. A Component Version describes what belongs to a particular version of a software component and how to access it. This includes: 107 | 108 | * resources, i.e. technical artifacts like binaries, docker images, ... 109 | * sources like code in github 110 | * references to other software component versions 111 | 112 | Component Repositories are the persistent store for component versions. Their artifacts can be stored along their component descriptor or in other external repositories. 113 | -------------------------------------------------------------------------------- /doc/01-model/02-elements-toplevel.md: -------------------------------------------------------------------------------- 1 | # Core Elements of a Component Version 2 | 3 | The following section describes how a component (version) is specified in more detail. 4 | Please note that this section intends to give an overview and explain the principal 5 | elements and their structure. It is not a complete specification. 6 | See the [schemas](https://github.com/open-component-model/ocm/tree/main/resources) 7 | for a full definition. 8 | 9 | A component version describes artifacts, using several core elements. 10 | 11 | - Artifacts represent technical content. They appear in two different flavors: 12 | - *Sources* describe the sources a component version has been composed/generated from. 13 | - *Resources* describe the delivery artifacts contained in a component version. 14 | - References describe the aggregation of other component versions. 15 | 16 | All those described elements share a common set of metadata. 17 | 18 | ## Component Identity 19 | 20 | A *Component* is technically defined by a globally unique identifier. 21 | 22 | The component identity uses the following naming scheme: 23 | 24 | *\* `/` *\* { `/` *\* } 25 | 26 | Hereby the DNS domain plus optionally any number of leading name components MUST 27 | be owned by the provider of a component. For example, `github.com`, as DNS domain 28 | is shared by lots of organizations. Therefore, all component identities provided 29 | based on this DNS name, must include the owner prefix of the providing 30 | organization, e.g. `github.com/my-org`. 31 | 32 | The component acts as a namespace to host multiple *Component Versions*. 33 | 34 | A component version has a unique identity composed of the component identity 35 | and a version name following the [semantic versioning](https://semver.org) 36 | specification (e.g. `github.com/gardener/external-dns-management:0.15.1`). 37 | 38 | ## Artifacts (Resources and Sources) 39 | 40 | The Open Component Model distinguishes two kinds of artifacts: 41 | 42 | - *Sources* are optional artifacts that contain the sources, which 43 | were used to generate the deployment-relevant *Resources*. 44 | - *Resources* are artifacts that finally make up the deployment-relevant set of artifacts. 45 | 46 | An *Artifact* is a blob containing some data in a technical format. 47 | Every artifact described by the component version has 48 | 49 | - an *Identity* in the context of the component version 50 | - a type representing the kind of content and how it can be used 51 | - a set of labels 52 | - an Access Specification to technically access the content (blob) of the artifact 53 | - an optional digest of the artifact 54 | 55 | Those attributes are described by formal fields in the component descriptor: 56 | 57 | - The [element identity](./03-elements-sub.md#element-identity) 58 | fields are directly embedded 59 | 60 | - **`type`** (required) *string* 61 | 62 | The type of an artifact specifies the logical interpretation of an artifact 63 | and is independent of its concrete technical representation. 64 | 65 | - **`labels`** (optional) *[]Label* 66 | 67 | - **`access`** (required) *Access Specification* 68 | 69 | The access specification for the actual artifact (see below) 70 | 71 | ### Artifact Types 72 | 73 | The formal type of an artifact uniquely specifies the logical interpretation of an artifact and its kind, 74 | independent of its concrete technical representation. 75 | 76 | If there are different possible technical representations, 77 | the access specification determines the concrete format given by a media type used for the returned blob. 78 | 79 | For example, a helm chart (type `helmChart`) can be represented as OCI artifact 80 | or helm chart archive. Nevertheless, the technical meaning is the same. 81 | In both cases the artifact (resource)`type` will be `helmChart`. 82 | The acess specification however will be different. In the first case it will refer to the helm-chart archive. 83 | In the second case the access method type will be `ociArtifact`. 84 | 85 | ```yaml 86 | ... 87 | resources: 88 | - name: mariadb-chart 89 | version: 12.2.7 90 | type: helmChart 91 | relation: external 92 | access: 93 | type: helm 94 | helmChart: mariadb:12.2.7 95 | helmRepository: https://charts.bitnami.com/bitnami 96 | ``` 97 | 98 | ```yaml 99 | ... 100 | resources: 101 | - name: mariadb-chart 102 | version: 12.2.7 103 | type: helmChart 104 | relation: external 105 | access: 106 | type: ociArtifact 107 | imageReference: ghcr.io/open-component-model/helmexample/charts/mariadb:12.2.7 108 | ``` 109 | 110 | The access method type `ociArtifact` however is also used for container images: 111 | 112 | ```yaml 113 | ... 114 | resources: 115 | - name: mariadb-image 116 | version: 10.11.2 117 | relation: external 118 | type: ociImage 119 | access: 120 | type: ociArtifact 121 | imageReference: bitnami/mariadb:10.11.2 122 | ``` 123 | 124 | The resource type `ociImage` now describes an object that can be used as a container image. 125 | So, the technical representation in both cases will be an OCI image manifest. 126 | The semantics how these objects can be used are completely different. 127 | This is expressed by the `type` of the artifact. 128 | 129 | An artifact's kind and logical interpretation is encoded into a simple string. 130 | The artifact type must be globally unique. OCM defines a naming scheme to guarantee this uniqueness. 131 | 132 | There are two kinds of types: 133 | 134 | - Centrally defined type names managed by the OCM organization 135 | 136 | These types use flat names following a camel case scheme with the first character 137 | in lower case, for example `ociArtifact`. 138 | 139 | Their format is described by the following regular expression: 140 | 141 | ```regex 142 | [a-z][a-zA-Z0-9]* 143 | ``` 144 | 145 | - Vendor specific types 146 | 147 | Any organization may define dedicated types on their own. 148 | Nevertheless, the meaning of those types must be defined. 149 | There may be multiple such types provided by different organizations with the same meaning. 150 | Organizations should share and reuse such types instead of introducing new type names. 151 | 152 | To support a unique namespace for those type names vendor specific types 153 | MUST follow a hierarchical naming scheme based on DNS domain names. 154 | Every type name has to be preceded by a DNS domain owned by the providing organization, 155 | like `landscaper.gardener.cloud/blueprint`. The local type must follow the above rules 156 | for centrally defined type names and is appended, separated by a slash (`/`). 157 | 158 | So, the complete pattern looks as follows: 159 | 160 | ```text 161 | /[a-z][a-zA-Z0-9]* 162 | ``` 163 | 164 | [Artifact Types](../01-model/07-extensions.md#artifact-types) are an extension point within the OCM model. 165 | All existing artifact types are listed [here](../04-extensions/01-artifact-types/README.md). 166 | 167 | ## Sources 168 | 169 | A *Source* is an artifact which describes the sources that were used to generate one or more of the resources. Source elements do not have specific additional formal attributes. 170 | 171 | Example: 172 | 173 | ```yaml 174 | ... 175 | sources: 176 | - name: ocm_source 177 | version: 0.1.0 178 | type: git 179 | access: 180 | commit: 9b2cf6ced322c7b938533caa22d5a5f48105b3ab 181 | ref: refs/heads/main 182 | repoUrl: github.com/open-component-model/ocm 183 | type: github 184 | ``` 185 | 186 | Currently there is only one source type defined: `github`. 187 | 188 | ## Resources 189 | 190 | A *Resource* is a delivery artifact, 191 | intended for deployment into a runtime environment, or describing additional 192 | content, relevant for a deployment mechanism. For example, installation procedures 193 | or meta-model descriptions controlling orchestration and/or deployment mechanisms. 194 | 195 | The Open Component Model makes no assumptions about how content described 196 | by the model is finally deployed or used. This is left to external tools. Tool 197 | specific deployment information is formally represented by other artifacts with 198 | an appropriate type. 199 | 200 | In addition to the common artifact information, a resource may optionally describe a reference to the source by specifying its artifact identity. 201 | 202 | A resource uses the following additional formal fields: 203 | 204 | - **`relation`** (required) *string['local', 'external']* 205 | Indicates whether the entity providing a component is also the provider of the resource ('local') or whether the 206 | resource is provided by a separate entity ('external'). This may be useful to determine whether the entity responsible 207 | for the component is also responsible for the resource. 208 | This property is purely informational and completely unrelated to the access method type. 209 | 210 | - **`digest`** (optional) *Digest Info* 211 | 212 | If the component descriptor is signed (directly or indirectly by one of its 213 | referencing component versions), a digest of a resource is stored along with 214 | the resource description. This is required because there might be different 215 | digest and resource normalization algorithms. 216 | 217 | - **`srcRefs`** (optional) *list of structs* 218 | 219 | This field is used to describe the sources used to generate the resource. 220 | The selection is done by the following two fields: 221 | 222 | - **`identitySelector`** *map[string]string* 223 | 224 | Identity attributes determining an appropriate source 225 | element. 226 | 227 | - **`labels`** (optional) *[]Label* 228 | 229 | A list of arbitrary labels 230 | 231 | Example: 232 | 233 | ```yaml 234 | ... 235 | resources: 236 | - name: image 237 | relation: external 238 | type: ociImage 239 | version: 1.0.0 240 | access: 241 | imageReference: gcr.io/google_containers/echoserver:1.10 242 | type: ociArtefact 243 | ``` 244 | 245 | The full list of resource types is [here](../04-extensions/01-artifact-types/README.md). 246 | 247 | ## References 248 | 249 | A component version may refer to other component versions by adding a *reference* to the component version. 250 | 251 | A *reference* does not have a blob, but it has: 252 | 253 | - an *Identity* in the context of the component version 254 | - a set of labels 255 | - an optional digest 256 | 257 | A `references` element has the following fields: 258 | 259 | - **`name`** (required) *string* 260 | 261 | The identity of the reference in this component version 262 | 263 | - **`componentName`** (required) *string* 264 | 265 | The identity of the referenced component. 266 | 267 | - **`version`** (required) *string* 268 | 269 | The version of the referenced component. 270 | 271 | - **`extraIdentity`** (optional) *map[string]string* 272 | 273 | The extra identity of the referenced component. 274 | 275 | - **`labels`** (optional) see below *[]Label* 276 | 277 | The extra identity of the referenced component. 278 | 279 | - **`digest`** (optional) see below *Digest Info* 280 | 281 | The extra identity of the referenced component. 282 | 283 | Example: 284 | 285 | ```yaml 286 | ... 287 | references: 288 | - name: installer 289 | version: 0.1.0 290 | componentName: github.com/open-component-model/ocmhelminstaller 291 | ``` 292 | 293 | ## Summary 294 | 295 | The OCM model describes component versions. A component version is stored in a component repository and consists of sources, resources and references. The component version itself as well as each resource, source and reference has an identity. Only sources and resources have content and therefore an access specification and an optional digest. All elements can have labels. 296 | -------------------------------------------------------------------------------- /doc/01-model/04-example.md: -------------------------------------------------------------------------------- 1 | 2 | # Example of a complete Component Version 3 | 4 | ```yaml 5 | # Example for a signed component descriptor containing three resources and one reference 6 | meta: 7 | configuredSchemaVersion: v2 # schema version 8 | component: 9 | name: github.com/open-component-model/ocmechoserver # name of this component 10 | version: 0.1.0-dev # version of this component 11 | provider: # provider of this component 12 | name: open-component-model 13 | repositoryContexts: # origin of this document 14 | - baseUrl: ghcr.io 15 | componentNameMapping: urlPath 16 | subPath: jensh007/ctf 17 | type: OCIRegistry 18 | componentReferences: # components referenced by this component 19 | - componentName: github.com/mandelsoft/ocmhelminstaller # name of referenced component 20 | name: installer # name of reference in this component descriptor 21 | version: 0.1.0-dev # version of referenced component 22 | digest: # digest used for signing this referenced component 23 | hashAlgorithm: sha256 24 | normalisationAlgorithm: jsonNormalisation/v1 25 | value: d1871d98a6b9ec11b562895efccdcb8b8f87d8dcb81eabc40cad4d9b68f0ea36 26 | resources: # resources making this component 27 | - name: image # name of this resource 28 | version: "1.0" # version of this resource 29 | type: ociImage # type of the resource (here indicating a container image) 30 | relation: external # resource is provided by a different entity than the component 31 | access: # access information how to locate this resource 32 | imageReference: gcr.io/google_containers/echoserver:1.10 33 | type: ociArtifact 34 | digest: # digest of this resource used for signing 35 | hashAlgorithm: sha256 36 | normalisationAlgorithm: ociArtifactDigest/v1 37 | value: cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 38 | - name: chart # name of this resource 39 | version: 0.1.0-dev # version of this resource 40 | type: helmChart # type of the resource (here indicating a helm chart) 41 | relation: local # resource is provided by the same entity as the component 42 | access: # access information how to locate this resource 43 | imageReference: ghcr.io/jensh007/ctf/github.com/open-component-model/ocmechoserver/echoserver:0.1.0 44 | type: ociArtifact 45 | digest: # digest of this resource used for signing 46 | hashAlgorithm: sha256 47 | normalisationAlgorithm: ociArtifactDigest/v1 48 | value: 385531bf40fc2b93e1693c0270250deb8da488a8f6f8dcaa79b0ab2bf1041c0b 49 | - name: package # name of this resource 50 | version: 0.1.0-dev # version of this resource 51 | type: toiPackage # type of the resource (here indicating a custom tyoe) 52 | relation: local # resource is provided by the same entity as the component 53 | access: # access information how to locate this resource 54 | globalAccess: 55 | digest: sha256:57563cb451bb79eb1c4bf0e71c66fdad1daf44fe55e128f12eae5f7e5496a188 56 | mediaType: application/vnd.toi.ocm.software.package.v1+yaml 57 | ref: ghcr.io/jensh007/ctf/component-descriptors/github.com/open-component-model/ocmechoserver 58 | size: 615 59 | type: ociBlob 60 | localReference: sha256:57563cb451bb79eb1c4bf0e71c66fdad1daf44fe55e128f12eae5f7e5496a188 61 | mediaType: application/vnd.toi.ocm.software.package.v1+yaml 62 | type: localBlob 63 | labels: # labels on this resource as key-value pairs 64 | - name: commit 65 | value: 9b2cf6ced322c7b938533caa22d5a5f48105b3ab 66 | digest: # digest of this resource used for signing 67 | hashAlgorithm: sha256 68 | normalisationAlgorithm: genericBlobDigest/v1 69 | value: 57563cb451bb79eb1c4bf0e71c66fdad1daf44fe55e128f12eae5f7e5496a188 70 | sources: # information about the origin (source code) of this component 71 | - name: echoserver_source # name of the source 72 | version: 0.1.0-dev # version of this source 73 | type: git # type of the source (here Git repository) 74 | access: # access information how to locate this resource 75 | commit: 9b2cf6ced322c7b938533caa22d5a5f48105b3ab 76 | ref: refs/heads/main 77 | repoUrl: github.com/open-component-model/ocm 78 | type: github 79 | signatures: # signing information using cryptographic signatures 80 | - name: mysig # name of this signature 81 | digest: # digest of this signature including used algorithm 82 | hashAlgorithm: sha256 83 | normalisationAlgorithm: jsonNormalisation/v1 84 | value: cf08abae08bb874597630bc0573d941b1becc92b4916cbe3bef9aa0e89aec3f6 85 | signature: # signature including used algorithm 86 | algorithm: RSASSA-PKCS1-V1_5 87 | mediaType: application/vnd.ocm.signature.rsa 88 | value: 390157b7311538bc50e31d126b413b49e2ec85a6bc16a4fe6a27fbc9f9b6f89bc9ac48091beff3d091a9eb0a62a35e0eb2b6f5ab35c3cdde6cfad3437d660894ecc9a4e42cc4664ade28e74c478d69fe791d18b81fb31ee6c5633a9ea2543e868281dd6de6d29b68200ba135fd5718b3fc0ac1cd437910d06c9a88753e00b7e5b778bf52d668a5e20e0f857702c5c03abc42933af2af00b701722c50835bc5f9d85fd523654647e49dccdede1e17f20e4a6b30037d3d151e08c58c2aabe638028dbfddbd4a63e4efb07983631e1cb98902677e7e17b9e5192d4a6c178ec694eaa260f7a7845378019ce3368082c466a4ff54d823191f44db61b7aa75ab2705d6 89 | ``` 90 | -------------------------------------------------------------------------------- /doc/01-model/06-conventions.md: -------------------------------------------------------------------------------- 1 | # Conventions 2 | 3 | To ensure uniformity across tools that interact with content from the component model, 4 | certain conventions should be adhered to. 5 | 6 | These conventiones are not covered by the [model-tool contract](../05-guidelines/02-contract.md#model-contract). 7 | They are also not part of the specificationsbut should be obeyed 8 | to achieve a common understanding about the meaning of content. 9 | 10 | ## Intended Environments 11 | 12 | There are several scenarios where artifacts will be provided as content of [component versions](./02-elements-toplevel.md#components-and-component-versions), which might be bound to a dedicated runtime environment. If a component version should provide several flavors of the same artifact intended for different environments they should use the same element name and version, and the environment should be reflected by one or more [extra identity properties](./03-elements-sub.md#identifiers). 13 | 14 | ### Operating System and CPU Architecture 15 | 16 | For executables and container images the specification for [OCI image indices](https://github.com/opencontainers/image-spec/blob/main/image-index.md#image-index-property-descriptions) should be used. 17 | 18 | The following extra identity properties are defined: 19 | 20 | - **`os`**: the operating system the element is intended for. It SHOULD use values listed in the Go Language document for [GOOS](https://go.dev/doc/install/source#environment). 21 | - **`architecture`**: the CPU architecture the element is intended for. It should use values listed in the Go Language document for [GOARCH](https://go.dev/doc/install/source#environment). 22 | 23 | This convention is also used by the OCM command line command [ocm download resource -x ...](https://github.com/open-component-model/ocm/blob/main/docs/reference/ocm_download_resources.md) to download an executable for the actual runtime environment. 24 | 25 | If platform specific images are described as separate resources instead of using a multiarch image, these extra identities should also be used. 26 | 27 | ## Selection of Usage Scenarios 28 | 29 | Usage scenarios for sets of described artifacts are best described by a dedicated description artifact with a dedicated tool-specific artifact type. Here, there is the complete freedom to describe the conditions and environments artifacts are to be used. The artifacts are described by [relative resource references](../05-guidelines/03-references.md#relative-artifact-references) in relation to the component version containing the description artifact. 30 | 31 | Another possibility is to use dedicated [labels](./03-elements-sub.md#labels) to describe the usage scenario for dedicated artifacts. Here, the tool working on a component versions does not read a description artifact, but has to analyse the label settings of all the provided artifacts. In both cases there is a dedicated OCM specific interpretation of content provided by the component model. But while the first solution allows to describe a closed scenario in a dedicated resource, where resources from dependent component version can be described by relative resource references and multiple scenarios can be separated by multiple flavors of this resource, the label-based approach is restricted to a local component version and a single scenario. Instead of an artifact type for the description, labels with a defined [name structure](./03-elements-sub.md#labels) are required. 32 | -------------------------------------------------------------------------------- /doc/01-model/README.md: -------------------------------------------------------------------------------- 1 | # Model (Core) 2 | 3 | This chapter describes the elements of the Open Component Model and their syntax. 4 | 5 | * 1.[OCM Model](01-model.md#ocm-model) 6 | * 1.1.[Introduction](01-model.md#introduction) 7 | * 1.2.[Components and Component Versions](01-model.md#components-and-component-versions) 8 | * 1.3.[Component Repositories](01-model.md#component-repositories) 9 | * 1.3.1.[Repository Types](01-model.md#repository-types) 10 | * 1.4.[Summary](01-model.md#summary) 11 | * 2.[Core Elements of a Component Version](02-elements-toplevel.md#core-elements-of-a-component-version) 12 | * 2.1.[Component Identity](02-elements-toplevel.md#component-identity) 13 | * 2.2.[Artifacts (Resources and Sources)](02-elements-toplevel.md#artifacts-resources-and-sources) 14 | * 2.2.1.[Artifact Types](02-elements-toplevel.md#artifact-types) 15 | * 2.3.[Sources](02-elements-toplevel.md#sources) 16 | * 2.4.[Resources](02-elements-toplevel.md#resources) 17 | * 2.5.[References](02-elements-toplevel.md#references) 18 | * 2.6.[Summary](02-elements-toplevel.md#summary) 19 | * 3.[Attributes of Elements of a Component Version](03-elements-sub.md#attributes-of-elements-of-a-component-version) 20 | * 3.1.[Element Identity](03-elements-sub.md#element-identity) 21 | * 3.2.[Access Specification](03-elements-sub.md#access-specification) 22 | * 3.4.[Labels](03-elements-sub.md#labels) 23 | * 3.5.[Repository Contexts](03-elements-sub.md#repository-contexts) 24 | * 3.6.[Signatures](03-elements-sub.md#signatures) 25 | * 3.7.[Digest Info](03-elements-sub.md#digest-info) 26 | * 3.8.[Signature Info](03-elements-sub.md#signature-info) 27 | * 4.[Example of a complete Component Version](04-example.md#example-of-a-complete-component-version) 28 | * 5.[Conventions](06-conventions.md#conventions) 29 | * 5.1.[Intended Environments](06-conventions.md#intended-environments) 30 | * 5.1.1.[Operating System and CPU Architecture](06-conventions.md#operating-system-and-cpu-architecture) 31 | * 5.2.[Selection of Usage Scenarios](06-conventions.md#selection-of-usage-scenarios) 32 | * 6.[Extending the Open Component Model](07-extensions.md#extending-the-open-component-model) 33 | * 6.1.[Component Descriptor Serialization](07-extensions.md#component-descriptor-serialization) 34 | * 6.2.[Storage Backends](07-extensions.md#storage-backends) 35 | * 6.2.1.[Data Formats](07-extensions.md#data-formats) 36 | * 6.2.2.[Mandatory Operations](07-extensions.md#mandatory-operations) 37 | * 6.2.3.[Optional Operations](07-extensions.md#optional-operations) 38 | * 6.3.[Access Methods](07-extensions.md#access-methods) 39 | * 6.3.1.[Access Specification](07-extensions.md#access-specification) 40 | * 6.3.2[Access Method Names](07-extensions.md#access-method-names) 41 | * 6.3.3.[Access specification format](07-extensions.md#access-specification-format) 42 | * 6.3.4[Access Method Operations](07-extensions.md#access-method-operations) 43 | * 6.4.[Digest Algorithms](07-extensions.md#digest-algorithms) 44 | * 6.5.[Signing Algorithms](07-extensions.md#signing-algorithms) 45 | * 6.6.[Artifact Normalization](07-extensions.md#artifact-normalization) 46 | * 6.7.[Component Descriptor Normalization](07-extensions.md#component-descriptor-normalization) 47 | * 6.7.1.[Signing-relevant Information in Component Descriptors](07-extensions.md#signing-relevant-information-in-component-descriptors) 48 | * 6.7.2.[Artifacts](07-extensions.md#artifacts) 49 | * 6.7.3.[Labels](07-extensions.md#labels) 50 | * 6.7.4.[References](07-extensions.md#references) 51 | * 6.7.5.[Applying Normalization Algorithms](07-extensions.md#applying-normalization-algorithms) 52 | * 6.8.[Label Merge Algorithms](07-extensions.md#label-merge-algorithms) 53 | * 6.9.[Artifact Types](07-extensions.md#artifact-types) 54 | * 6.10.[Label Types](07-extensions.md#label-types) 55 | * 6.10.1.[Format Versions](07-extensions.md#format-versions) 56 | * 6.10.2.[Predefined Labels](07-extensions.md#predefined-labels) 57 | -------------------------------------------------------------------------------- /doc/01-model/ocm-helm-indirect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/01-model/ocm-helm-indirect.png -------------------------------------------------------------------------------- /doc/01-model/ocm-helm-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/01-model/ocm-helm-simple.png -------------------------------------------------------------------------------- /doc/01-model/ocmidentity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/01-model/ocmidentity.png -------------------------------------------------------------------------------- /doc/01-model/ocmresourceaccess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/01-model/ocmresourceaccess.png -------------------------------------------------------------------------------- /doc/02-processing/01-references.md: -------------------------------------------------------------------------------- 1 | # Referencing 2 | 3 | A component version may refer to other component versions by adding a reference to the component version. This can be used to compose *aggregations* of component versions. 4 | 5 | A component version reference describes only the component version and no location or OCM repository. It is always evaluated in the actual repository context. In this way references are stable across transports. To keep a unique addressing scheme, like artifacts, references have an identity. 6 | 7 | A component version reference refers to another component version by using its identifier. A source or resource of the target component is identified by its `name` attribute (which must be unique within a component version). 8 | 9 | ## Example 10 | 11 | Let's take the following component: 12 | 13 | ```yaml 14 | component: 15 | name: github.com/jensh007/mariadb 16 | version: 10.11.2 17 | provider: ocm.software 18 | repositoryContexts: 19 | - baseUrl: eu.gcr.io 20 | componentNameMapping: urlPath 21 | subPath: sap-cp-k8s-ocm-gcp-eu30-dev/dev/d058463/microblog 22 | type: OCIRegistry 23 | resources: 24 | ... 25 | sources: 26 | ... 27 | meta: 28 | ... 29 | ``` 30 | 31 | Here we have a component version mariadb:10.11.2 living in repository context `eu.gcr.io` at some path. Let's take a second component, referring to the this one: 32 | 33 | ```yaml 34 | component: 35 | name: github.com/jensh007/microblog-deployment 36 | version: 0.23.1 37 | provider: ocm.software 38 | repositoryContexts: 39 | - baseUrl: eu.gcr.io 40 | componentNameMapping: urlPath 41 | subPath: sap-cp-k8s-ocm-gcp-eu30-dev/dev/d058463/microblog 42 | type: OCIRegistry 43 | resources: [] 44 | sources: [] 45 | componentReferences: 46 | ... 47 | - componentName: github.com/jensh007/mariadb 48 | name: mariadb 49 | version: 10.11.2 50 | ... 51 | meta: 52 | ... 53 | ``` 54 | 55 | The reference target is described by the component version identifier and not by the repository location. 56 | -------------------------------------------------------------------------------- /doc/02-processing/02-signing.md: -------------------------------------------------------------------------------- 1 | # Signing 2 | 3 | Signing of a component version consists of several steps: 4 | 5 | 1. digests for all reference component versions are determined and put 6 | into the dedicated reference element of the component descriptor. 7 | This is done by recursively following this procedure, but without the signing step. 8 | 2. digests for all described artifacts are determined and put into the dedicated 9 | element entry in the component descriptor (sources, resources) 10 | 3. the resulting component descriptor is normalized 11 | and a digest is calculated according to the selected digest algorithm. The resulting 12 | digest is stored in the component descriptor 13 | 4. the digest is signed with the selected signing algorithm and stored in the 14 | component descriptor. 15 | 5. the final component descriptor is updated in the OCM repository. 16 | 17 | The digest fields *MUST* be calculated during the signing process and already existing 18 | digest fields *CAN NOT* be trusted. Resources have to be accessed and 19 | digests has to be determined according to the combination of artifact 20 | normalization and digest algorithm and verified against existing digests. 21 | Component version references have to be followed recursively, calculating the 22 | digest for the referenced component descriptor. If digests fields for resources or 23 | component references already exist, they have to be compared against 24 | the calculated digest and rejected if different. 25 | 26 | The algorithms used for signing are listed in the [extensions](../04-extensions/04-algorithms/README.md#signature-algorithms). 27 | 28 | ## Verification Procedure 29 | 30 | Verifying a component descriptor consist of three steps. Any failing step 31 | **MUST** fail the validation. 32 | 33 | 1. Verify the digest of all resources and component references. Recursively follow component references and create an in-memory representation of the referenced component-descriptor by accessing and digesting all resources and references. Do not trust any digest data in child component-descriptors. The digest of the normalised in-memory representation of a component-reference **MUST** match the digest in the root component-descriptor (that contains a signature we verify in the next step). 34 | 35 | ```go 36 | func digestForComponentDescriptor(cd) -> digest: 37 | for reference in cd.component.componentReferences: 38 | referencedCd = loadCdForReference(reference) 39 | reference.Digest = digestForComponentDescriptor(referencedCd) 40 | 41 | for resource in cd.component.Resource: 42 | resource.Digest = loadAndDigestResource(resource) 43 | 44 | normalisedCd = normaliseComponentDescriptor(cd) 45 | digest = createDigestForNormalisedCd 46 | return digest 47 | ``` 48 | 49 | 2. check if calculated digest of the normalized component descriptor matches the 50 | digest in signatures.digest with hashAlgorithm, NormalisationAlgorithm and Value 51 | 3. verify the signature for the digest of the component descriptor. 52 | 53 | ### Verify with RSA 54 | 55 | Signature verification with RSASSA-PKCS1-V1_5 requires a Public Key. This is used in step 3 of the 56 | verification algorithm. 57 | 58 | ### Verify with X509 59 | 60 | Signature verification with X509 certificates require a validation of the 61 | *signing* certificate and the signature itself. First, the validity of the 62 | signing certificate is checked with a root CA and a chain of intermediate 63 | certificates. The certificate requires the usage types `x509.KeyUsageDigitalSignature` and 64 | `x509.ExtKeyUsageCodeSigning`. Afterwards, the CD signature is verified with the public key in 65 | the signing certificate. If the signature entry of the component version describes an issuer it is 66 | validated against the common name of the certificate. 67 | -------------------------------------------------------------------------------- /doc/02-processing/03-signing-process.md: -------------------------------------------------------------------------------- 1 | # Signing Process and Normalization 2 | 3 | The signing of a component version is based on three things: 4 | 5 | * selected content of the component descriptor 6 | * the content of the described artifacts 7 | * the referenced component versions. 8 | 9 | A signature of a component version is based on digests of the involved elements. 10 | Therefore, there must be a defined way, how to calculate digests. 11 | This has to happen in a recursive way to handle aggregations. 12 | 13 | ## Determing the Artifact Digests 14 | 15 | The content of every artifact is provided in a dedicated blob format by the various access methods. 16 | A digest can be calculated based on this blob. This is the default behaviour. 17 | 18 | Nevertheless, there might be technology specific ways to provide an immutable digest for a dedicated type of artifact, 19 | independent of the blob format generation (typically an archive). 20 | For example, an OCI artifact is always uniquely identified by its manifest digest. 21 | This characteristic can be used for the calculation of OCM artifact digests. 22 | 23 | There might be various ways to determine a digest for an artifact blob. 24 | The algorithm to do this is called *artifact normalization type*. 25 | Together with the digest and its digesting algorithm (e.g. SHA-256) 26 | the normalization type is kept for an artifact. 27 | 28 | Example for the digest of an OCI artifact: 29 | 30 | ```yaml 31 | digest: 32 | hashAlgorithm: SHA-256 33 | normalisationAlgorithm: ociArtifactDigest/v1 34 | value: 5e28862f7ad5b71f3f5c5dc7a4ccc8c3d3cb87f5e5774458d895d831d3765548 35 | ``` 36 | 37 | This normalization algorithm specifies the way the digest is determined. For example, for OCI artifacts, 38 | the algorithm `ociArtifactDigest/v1` is used by default. This behaviour can be controlled by appropriate digest handlers. 39 | 40 | If not explicitly requested, an appropiate digest handler is automatically determined based on the available digest handlers, 41 | when the digest of an artifact is calculated for the first time. 42 | This selection depends on the media type of the artifact blob and the artifact type. 43 | 44 | Normalization algorithm types may be versioned and SHOULD match the following regexp 45 | 46 | ```text 47 | [a-z][a-zA-Z0-9]*/v[0-9]+([a-z][a-z0-9]*) 48 | ``` 49 | 50 | For example: `ociArtifactDigest/v1` or `jsonNormalisationV2` 51 | 52 | If the digest algorithm `NO-DIGEST` is specified for an artifact, 53 | this artifact content is not included into the component version digest. 54 | This is typically configured for source artifacts, which are not deliverable. 55 | 56 | The artifact digest normalization algorithms are listed in the [extensions](../04-extensions/04-algorithms/README.md#artifact-normalization-types) 57 | section of the specification. 58 | 59 | ## Normalization Types 60 | 61 | To be able to sign a component version, the content of the described artifacts must be incorporated 62 | and a digest for the artifact content needs to be calculated. 63 | 64 | By default, this digest is calculated based on the blob provided by the access specification of an artifact. There might be technology specific ways to uniquely identify the content for specific artifact types. 65 | 66 | Together with the digest and its algorithm, an artifact normalization algorithm is specified in the component descriptor. 67 | 68 | It contains signature 69 | relevant information and volatile information (e.g. the access specification). Therefore, there is a normalization for component descriptors. 70 | 71 | Normalization algorithm types may be versioned and SHOULD match the following regexp 72 | 73 | ```text 74 | [a-z][a-zA-Z0-9]*/v[0-9]+([a-z][a-z0-9]*) 75 | ``` 76 | 77 | For example: `ociArtifactDigest/v1` or `jsonNormalisationV2` 78 | 79 | The normalization algorithms are listed in the [extensible parts](../04-extensions/04-algorithms/component-descriptor-normalization-algorithms.md) of the specification 80 | 81 | ## Serialization Format 82 | 83 | A digest for a component version is stored along with a signature in a 84 | component descriptor. A component descriptor can have multiple signatures and with this 85 | multiple digests. 86 | 87 | Example: 88 | 89 | ```text 90 | digest: 91 | hashAlgorithm: SHA-256 92 | normalisationAlgorithm: jsonNormalisation/v2 93 | value: 01c211f5c9cfd7c40e5b84d66a2fb7d19cb0d65174b06c57b403c2ad9fdf8ed2 94 | ``` 95 | 96 | ## Recursive Digest Calculation 97 | 98 | A digest for a component version is calculated recursively including all referenced component versions. For each referenced component the component descriptor will get a `digest` section for each `reference` contained in `spec`: 99 | 100 | ```yaml 101 | spec: 102 | ... 103 | references: 104 | - componentName: ocm.software/simpleapp 105 | digest: 106 | hashAlgorithm: SHA-256 107 | normalisationAlgorithm: jsonNormalisation/v2 108 | value: 01c211f5c9cfd7c40e5b84d66a2fb7d19cb0d65174b06c57b403c2ad9fdf8ed2 109 | name: myhelperapp 110 | version: 0.1.0 111 | ``` 112 | -------------------------------------------------------------------------------- /doc/02-processing/04-signing-examples.md: -------------------------------------------------------------------------------- 1 | # Examples for Signing of Component Versions 2 | 3 | ## Simple Component Version 4 | 5 | The component descriptor to be signed is: 6 | 7 | ```yaml 8 | apiVersion: ocm.software/v3alpha1 9 | kind: ComponentVersion 10 | metadata: 11 | name: ocm.software/simpleapp 12 | provider: 13 | name: ocm.software 14 | version: 0.1.0 15 | repositoryContexts: [] 16 | spec: 17 | resources: 18 | - access: 19 | localReference: sha256:dea5de3e6f20fc58bfa8c2a25043f628c730960d46100b83540a30ed0a4e7910 20 | mediaType: application/vnd.oci.image.manifest.v1+tar+gzip 21 | referenceName: ocm.software/simpleapp/echoserver:0.1.0 22 | type: localBlob 23 | name: chart 24 | relation: local 25 | type: helmChart 26 | version: 0.1.0 27 | - access: 28 | imageReference: gcr.io/google_containers/echoserver:1.10 29 | type: ociArtifact 30 | name: image 31 | relation: external 32 | type: ociImage 33 | version: "1.0" 34 | sources: 35 | - access: 36 | commit: e39625d6e919d33267da4778a1842670ce2bbf77 37 | repoUrl: github.com/open-component-model/ocm 38 | type: github 39 | name: source 40 | type: filesytem 41 | version: 0.1.0 42 | ``` 43 | 44 | The normalized form of the component descriptor in `jsonNormalisation/v2` is the string: 45 | 46 | ```json 47 | [{"component":[{"componentReferences":[]},{"name":"ocm.software/simpleapp"},{"provider":[{"name":"ocm.software"}]},{"resources":[[{"digest":[{"hashAlgorithm":"SHA-256"},{"normalisationAlgorithm":"ociArtifactDigest/v1"},{"value":"5e28862f7ad5b71f3f5c5dc7a4ccc8c3d3cb87f5e5774458d895d831d3765548"}]},{"name":"chart"},{"relation":"local"},{"type":"helmChart"},{"version":"0.1.0"}],[{"digest":[{"hashAlgorithm":"SHA-256"},{"normalisationAlgorithm":"ociArtifactDigest/v1"},{"value":"cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229"}]},{"name":"image"},{"relation":"external"},{"type":"ociImage"},{"version":"1.0"}]]},{"sources":[[{"name":"source"},{"type":"filesytem"},{"version":"0.1.0"}]]},{"version":"0.1.0"}]}] 48 | ``` 49 | 50 | The `SHA-256` digest of this string is: `01c211f5c9cfd7c40e5b84d66a2fb7d19cb0d65174b06c57b403c2ad9fdf8ed2` 51 | 52 | Adding the signature and digests for all artifacts leads to this signed component descriptor: 53 | 54 | ```yaml 55 | apiVersion: ocm.software/v3alpha1 56 | kind: ComponentVersion 57 | metadata: 58 | name: ocm.software/simpleapp 59 | provider: 60 | name: ocm.software 61 | version: 0.1.0 62 | repositoryContexts: [] 63 | signatures: 64 | - digest: 65 | hashAlgorithm: SHA-256 66 | normalisationAlgorithm: jsonNormalisation/v2 67 | value: 01c211f5c9cfd7c40e5b84d66a2fb7d19cb0d65174b06c57b403c2ad9fdf8ed2 68 | name: mysig 69 | signature: 70 | algorithm: RSASSA-PKCS1-V1_5 71 | mediaType: application/vnd.ocm.signature.rsa 72 | value: ae7e7a215d970c036773221642693bded5cf6a039597113d5ec522d5ebd491a40e3f6d850689a749aaa2de3c0cc2a9e5f564c8353f514385fae7c9554e00aead4890483a0ae5cef5c3629eb63ba4ee061659b06737b4985b4c04d286d19a09735482a769e82dd4a0b396cb0dda0822817b72b7daa1dfd2a1c071dd4a7e7bea1e25ee4156594efc5a567ac092ae8518995843bef1e79c7bfd95651cf66725f3740ef8b0202485900a0445df327543963322baf61dd91d4b30356b996bd99e513e2b5a7643a8ddfc706773603dfb3f8f38d7a9fbd10c48fe813c8149b1e0be20f7fcf54bdd5efe4da37c60730fbf33f3ea26b793cf6ac531b8c6f66bea3e3d2ffc 73 | spec: 74 | resources: 75 | - access: 76 | localReference: sha256:dea5de3e6f20fc58bfa8c2a25043f628c730960d46100b83540a30ed0a4e7910 77 | mediaType: application/vnd.oci.image.manifest.v1+tar+gzip 78 | referenceName: ocm.software/simpleapp/echoserver:0.1.0 79 | type: localBlob 80 | digest: 81 | hashAlgorithm: SHA-256 82 | normalisationAlgorithm: ociArtifactDigest/v1 83 | value: 5e28862f7ad5b71f3f5c5dc7a4ccc8c3d3cb87f5e5774458d895d831d3765548 84 | name: chart 85 | relation: local 86 | type: helmChart 87 | version: 0.1.0 88 | - access: 89 | imageReference: gcr.io/google_containers/echoserver:1.10 90 | type: ociArtifact 91 | digest: 92 | hashAlgorithm: SHA-256 93 | normalisationAlgorithm: ociArtifactDigest/v1 94 | value: cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 95 | name: image 96 | relation: external 97 | type: ociImage 98 | version: "1.0" 99 | sources: 100 | - access: 101 | commit: e39625d6e919d33267da4778a1842670ce2bbf77 102 | repoUrl: github.com/open-component-model/ocm 103 | type: github 104 | name: source 105 | type: filesytem 106 | version: 0.1.0 107 | ``` 108 | 109 | ## Component Version with Reference 110 | 111 | Here is a component descriptor containing a reference to the component in the previous [example](#simple-component-version). 112 | 113 | ```yaml 114 | apiVersion: ocm.software/v3alpha1 115 | kind: ComponentVersion 116 | metadata: 117 | name: ocm.software/complexapp 118 | provider: 119 | name: ocm.software 120 | version: 0.1.0 121 | repositoryContexts: [] 122 | spec: 123 | references: 124 | - componentName: ocm.software/simpleapp 125 | name: myhelperapp 126 | version: 0.1.0 127 | resources: 128 | - access: 129 | imageReference: gcr.io/google_containers/pause:3.2 130 | type: ociArtifact 131 | name: image 132 | relation: external 133 | type: ociImage 134 | version: "1.0" 135 | ``` 136 | 137 | The normalized form of the component descriptor in `jsonNormalisation/v2` is the string: 138 | 139 | ```json 140 | [{"component":[{"componentReferences":[[{"componentName":"ocm.software/simpleapp"},{"digest":[{"hashAlgorithm":"SHA-256"},{"normalisationAlgorithm":"jsonNormalisation/v2"},{"value":"01c211f5c9cfd7c40e5b84d66a2fb7d19cb0d65174b06c57b403c2ad9fdf8ed2"}]},{"name":"myhelperapp"},{"version":"0.1.0"}]]},{"name":"ocm.software/complexapp"},{"provider":[{"name":"ocm.software"}]},{"resources":[[{"digest":[{"hashAlgorithm":"SHA-256"},{"normalisationAlgorithm":"ociArtifactDigest/v1"},{"value":"927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f"}]},{"name":"image"},{"relation":"external"},{"type":"ociImage"},{"version":"1.0"}]]},{"sources":[]},{"version":"0.1.0"}]}] 141 | ``` 142 | 143 | The `SHA-256` digest of this string is: `01801dfb56ba7b4033b8177e53e689644f1447c8270004b2c05c5fe45aa1063f` 144 | 145 | Adding the signature and digests for all artifacts leads to this signed component descriptor: 146 | 147 | ```yaml 148 | apiVersion: ocm.software/v3alpha1 149 | kind: ComponentVersion 150 | metadata: 151 | name: ocm.software/complexapp 152 | provider: 153 | name: ocm.software 154 | version: 0.1.0 155 | repositoryContexts: [] 156 | signatures: 157 | - digest: 158 | hashAlgorithm: SHA-256 159 | normalisationAlgorithm: jsonNormalisation/v2 160 | value: 01801dfb56ba7b4033b8177e53e689644f1447c8270004b2c05c5fe45aa1063f 161 | name: mysig 162 | signature: 163 | algorithm: RSASSA-PKCS1-V1_5 164 | mediaType: application/vnd.ocm.signature.rsa 165 | value: 727b067cd67003338b83149220a36fdb7e16f29d4d5790474c95ee3547adcbe64d699efce3d19fa2e85424904265c0364e95f15cbf816e093b633943a632ba9f3b862e1f5adb62620cf7eb2d85b60796f329afb1df26019ca84b42c58ebc6e691094e34eca223195f96cee3a8a1552e4ac7d1821e32072213f6cc762355c5974be56f239a270a9c67056ec3455f10339eb76eb8ca1905f0201190130fac0683bc2d09fa9bc3a9cd30af414b6f29e97397621d2f6b715353a7f793813139ed9707824b648aa84f2b38cc27fd7f6e89633ba83eb1fd34ab68a3b9c098eddd659f94a06d0225a4ed607b4c7682ca8d824ee005e618a25d3dde9d6aaf626aa7e1556 166 | spec: 167 | references: 168 | - componentName: ocm.software/simpleapp 169 | digest: 170 | hashAlgorithm: SHA-256 171 | normalisationAlgorithm: jsonNormalisation/v2 172 | value: 01c211f5c9cfd7c40e5b84d66a2fb7d19cb0d65174b06c57b403c2ad9fdf8ed2 173 | name: myhelperapp 174 | version: 0.1.0 175 | resources: 176 | - access: 177 | imageReference: gcr.io/google_containers/pause:3.2 178 | type: ociArtifact 179 | digest: 180 | hashAlgorithm: SHA-256 181 | normalisationAlgorithm: ociArtifactDigest/v1 182 | value: 927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f 183 | name: image 184 | relation: external 185 | type: ociImage 186 | version: "1.0" 187 | ``` 188 | 189 | Note that the `references` section in `spec` now contains a `digest` for the referenced component `ocm.software/simpleapp`. The value of the digest therefore is the same as in the previous example. 190 | -------------------------------------------------------------------------------- /doc/02-processing/05-component-descriptor-normalization.md: -------------------------------------------------------------------------------- 1 | # Component Descriptor Normalization 2 | 3 | The component descriptor contains several kinds of information: 4 | 5 | * volatile label settings, which might be changeable. 6 | * artifact access information, which might be changed during transport steps. 7 | * static information describing the features and artifacts of a component version. 8 | 9 | The digest of a component descriptor is calculated on a normalized form of the 10 | elements of the component descriptor. The normalized form contains only the signature 11 | relevant information, everything else gets removed during the normalization process. 12 | The resulting string is the source for calculating the digest. This digest is then finally signed (and verified). 13 | 14 | A normalized component descriptor is a subset of its elements containing only the properties relevant for signing: 15 | 16 | * based on JSON 17 | * map serializes as alphanumerically ordered list of fields (to define unique order) 18 | * field is map with two keys 'name', 'value' 19 | 20 | Like for signature algorithms, the model offers the possibility to work with 21 | different normalization algorithms and formats. 22 | 23 | The algorithms used for normalization are listed in the [extensible parts](../04-extensions/04-algorithms/component-descriptor-normalization-algorithms.md) of the specification. 24 | 25 | ## Signing-relevant Information in Component Descriptors 26 | 27 | A component descriptor contains static information and 28 | information, which may change over time, e.g. access method 29 | specifications might be changed during transport steps. A digest should be 30 | stable even after a transport and therefore should only hash static 31 | information. Therefore, a component descriptor is transformed into a format 32 | that only contains immutable fields, finally relevant for the signing 33 | process and assuring data integrity. 34 | 35 | Relevant fields and their mapping to the normalized data structure for `JsonNormalisationV2` are: 36 | 37 | * Component Name: mapped to `component.name` 38 | * Component Version: mapped to `component.version` 39 | * Component Labels: mapped to `component.labels` (see [Labels](#labels)]) 40 | * Component Provider: mapped to `component.provider` 41 | * Resources: mapped to `component.resources`, always empty list enforced, without the source references (see [Labels](#labels)] and [Access Methods](#access-methods)]) 42 | * Sources: mapped to `component.sources`, always empty list enforced, (see [Labels](#labels)] and [Access Methods](#access-methods)]) 43 | * References: mapped to `component.references`, always empty list enforced, (see [Labels](#labels)]) 44 | 45 | ### Access Methods 46 | 47 | Access method specifications are completely ignored. 48 | A resource or source is ignored, if the access method type is `none`. 49 | 50 | ### Labels 51 | 52 | Labels by default are removed before signing, but can be marked with a special boolean 53 | property `signing`. This property indicates that the label is 54 | signing-relevant and therefore becomes part of the digest. As a consequence such 55 | labels cannot be changed during the lifecycle of a component version anymore 56 | and should only describe static information. 57 | The structure of signing-relevant labels is preserved from the component 58 | descriptor version `v2`. 59 | 60 | Example: 61 | 62 | ```yaml 63 | labels: 64 | - name: label1 65 | value: foo 66 | - name: label2 67 | value: bar 68 | signing: true 69 | ``` 70 | 71 | `label1` will be excluded from the digest, whereas `label2` will be included. 72 | The value of any label is taken as is, preserving a potentially deeply nested structure. 73 | 74 | ## Exclude Resources from Normalization/Signing 75 | 76 | If a resource should not be part of the normalization and later signing, the resource needs a special digest in the following format: 77 | 78 | ```yaml 79 | digest: 80 | hashAlgorithm: NO-DIGEST 81 | normalisationAlgorithm: EXCLUDE-FROM-SIGNATURE 82 | value: NO-DIGEST 83 | ``` 84 | 85 | ## Generic Normalization Format 86 | 87 | The generic format is based on a data structure consisting of dictionaries, lists and 88 | simple values, like strings and integers. 89 | 90 | The signing relevant information described by a component descriptor is mapped 91 | to such a data structure according to the format specifications described below. 92 | 93 | This data structure is mapped to a formal JSON representation, which 94 | only contains clearly ordered elements. It is marshalled without whitespaces contained 95 | in the representation. The resulting byte stream is directly defined 96 | by the inbound data structure and independent of the order of marshalling 97 | dictionaries/objects. 98 | Its digest can be used as basis for calculating a signature. 99 | 100 | To map lists and dictionaries into such clearly ordered elements the rules 101 | below are used. The inbound data structures in the examples are shown in 102 | YAML notation. 103 | 104 | ### Simple Values 105 | 106 | Simple values are kept as they are. 107 | 108 | Example: 109 | 110 | ```yaml 111 | "bob" 112 | ``` 113 | 114 | will result in : 115 | 116 | ```json 117 | "bob" 118 | ``` 119 | 120 | ### Dictionary 121 | 122 | All dictionaries are converted into lists where each element is a single-entry 123 | dictionary containing the key/value pair of the original entry. This list is 124 | ordered by lexicographical order of the keys. 125 | 126 | Example: 127 | 128 | ```yaml 129 | bob: 26 130 | alice: 25 131 | ``` 132 | 133 | will result in : 134 | 135 | ```json 136 | [{"alice":25},{"bob":26}] 137 | ``` 138 | 139 | The values are converted according to the same rules, recursively. 140 | 141 | Example: 142 | 143 | ```yaml 144 | people: 145 | bob: 26 146 | alice: 25 147 | ``` 148 | 149 | will result in : 150 | 151 | ```json 152 | [{"people":[{"alice":25},{"bob":26}]}] 153 | ``` 154 | 155 | ### Lists 156 | 157 | Lists are converted into JSON arrays and preserve the order of the elements. 158 | 159 | Example: 160 | 161 | ```yaml 162 | - bob 163 | - alice 164 | ``` 165 | 166 | normalized to: 167 | 168 | ```json 169 | ["bob","alice"] 170 | ``` 171 | 172 | The values are converted according to the same rules, recursively. 173 | 174 | Example: 175 | 176 | ```yaml 177 | - bob: 26 178 | - alice: 25 179 | ``` 180 | 181 | will result in : 182 | 183 | ```json 184 | [[{"bob":26}],[{"alice":25}]] 185 | ``` 186 | 187 | ### Combined example 188 | 189 | The following snippet is taken from a real component descriptor. 190 | 191 | ```yaml 192 | resources: 193 | - access: 194 | localReference: blob 195 | mediaType: text/plain 196 | referenceName: ref 197 | type: localBlob 198 | extraIdentity: 199 | additional: value 200 | other: othervalue 201 | name: elem1 202 | relation: local 203 | type: elemtype 204 | version: 1 205 | ``` 206 | 207 | This will be normalized to 208 | 209 | ```json 210 | [{"resources":[[{"access":[{"localReference":"blob"},{"mediaType":"text/plain"},{"referenceName":"ref"},{"type":"localBlob"}]},{"extraIdentity":[{"additional":"value"},{"other":"othervalue"}]},{"name":"elem1"},{"relation":"local"},{"type":"elemtype"},{"version":1}]]}] 211 | ``` 212 | 213 | Formatted with whitespaces for better readability it looks like: 214 | 215 | ```json 216 | [ 217 | { 218 | "resources": [ 219 | [ 220 | { 221 | "access": [ 222 | { 223 | "localReference": "blob" 224 | }, 225 | { 226 | "mediaType": "text/plain" 227 | }, 228 | { 229 | "referenceName": "ref" 230 | }, 231 | { 232 | "type": "localBlob" 233 | } 234 | ] 235 | }, 236 | { 237 | "extraIdentity": [ 238 | { 239 | "additional": "value" 240 | }, 241 | { 242 | "other": "othervalue" 243 | } 244 | ] 245 | }, 246 | { 247 | "name": "elem1" 248 | }, 249 | { 250 | "relation": "local" 251 | }, 252 | { 253 | "type": "elemtype" 254 | }, 255 | { 256 | "version": 1 257 | } 258 | ] 259 | ] 260 | } 261 | ] 262 | ``` 263 | 264 | ### Empty values 265 | 266 | Empty lists are normalized as empty lists 267 | 268 | ```yaml 269 | myList: [] 270 | ``` 271 | 272 | ```json 273 | [{"myList":[]}] 274 | ``` 275 | 276 | Null values are skipped during initialization 277 | 278 | ```yaml 279 | myList: ~ 280 | ``` 281 | 282 | ```yaml 283 | myList: null 284 | ``` 285 | 286 | ```yaml 287 | myList: 288 | ``` 289 | 290 | and are all normalized to: 291 | 292 | ```json 293 | [] 294 | ``` 295 | -------------------------------------------------------------------------------- /doc/02-processing/06-artifact-normalization.md: -------------------------------------------------------------------------------- 1 | # Artifact Normalization 2 | 3 | To be able to sign a component version a digest for the artifact **content** must be determined. 4 | 5 | By default, this digest is calculated based on the blob provided by the access specification. 6 | There might be technology specific ways to uniquely identify the content for dedicated artifact types. 7 | Therefore an artifact normalization algorithm is kept in the component descriptor. 8 | 9 | ## Blob Representation Format for Resource Types 10 | 11 | The central task of a component version is to provide information about versioned sets of resources. 12 | For the component model such content of resources are just simple typed blobs. 13 | The evaluation of an access specification always results in a simple blob, representing the content of the described resource. 14 | This way blobs can be stored in any supported external blob store. 15 | 16 | An access method MUST always be able to return a blob representation for the accessed artifact. 17 | If there are native storage technologies for dedicated artifact types they must also deliver such a blob. 18 | 19 | Whenever a new resource type is supported, corresponding blob formats MUST be defined for this type. 20 | Type-agnostic access method types, like `localBlob` or `ociBlob` never need to know anything about their internal format. 21 | But specific access methods, e.g. the `ociArtifact` method, MAY provide dedicated blob formats. 22 | 23 | These blob formats may depend on the combination of artifact type and access method type. 24 | Therefore, a blob always has a *media type* specifying the technical format. 25 | For every artifact type the possible media types with their technical format specifications MUST be defined. 26 | 27 | When using the component repository to transport content from one repository to 28 | another the access information may change. But all variants MUST describe the same 29 | content. 30 | 31 | If multiple media types are possible for blobs, the digest of the artifact content 32 | MUST be immutable to avoid invalidating signatures. In such a case a 33 | dedicated artifact normalization algorithm MUST be provided for such media types. 34 | 35 | Available artifact normalization types can be found [here](./03-signing-process.md#normalization-types). 36 | 37 | ## Interaction of Local Blobs, Access Methods, Uploaders and Media Types 38 | 39 | The Open Component Model is desiged to support transports of artifacts. 40 | To assure the integrity of digests and signatures some rules must be obeyed by the involved model extensions. 41 | 42 | ### Access Methods 43 | 44 | A remote access method MUST return the artifact content as blob. 45 | 46 | By default, this blob is used to calculate the content digest for an artifact. 47 | Therefore, the byte-stream of this blob must be deterministic. 48 | Multiple calls for the same content must return the identical blob. 49 | If this cannot be guaranteed, a blob digest handler for the media type of this blob format MUST be defined. 50 | 51 | For example, the `ociArtifact` access method provides content as artifact set blob, 52 | with a format based on the OCI artifact structure, which is defined by a dedicated media type. 53 | For this media type a digest handler is defined, which replaces the default blob digest by the manifest digest of the artifact. 54 | This way the digest is independent from the creation of the archive blob containing the artifact. 55 | 56 | Once the artifact content has been converted to a blob and stored as local blob, 57 | this blob is by default kept for further transport steps. 58 | This way, the digest calculation always provides the same result. 59 | 60 | ### Blob Uploaders 61 | 62 | Blob Uploaders can be used as part of the transport process, to automatically 63 | provide transported artifacts in technology specific local storage systems, e.g. OCI registries. 64 | The Open Component Model allows to change access locations 65 | of artifact content during transport. Therefore an automatic upload 66 | with modification of the access method is principally allowed. 67 | In such scenarios, it's essential to adhere to specific rules to ensure the integrity of digests and signatures. 68 | 69 | If a blob uploader is used to upload the artifact to a remote repository after a transfer again, 70 | the access method can potentially be changed. But this MUST guarantee the same digest calculation. 71 | The new access method must again provide a blob with a media type and digest handler combination, providing the same digest. 72 | 73 | For example, storing an OCI artifact delivered as local blob in an OCI repository again, the manifest digest will be the same. 74 | This is guaranteed because it is the identity of the artifact according to the OCI specification. 75 | As a result, a new transformation to a blob representation in combination with the digest handler 76 | will always provide the same artifact digest. The access method can be switched again, 77 | from `localBlob` to `ociArtifact` regardless of the artifact type. 78 | 79 | If this can not be guaranteed, once a blob representation is chosen, it must be kept as it is. 80 | In such a case a blob uploader must preserve the local access method, 81 | even if it uploads the content to an external storage system. 82 | 83 | This can be described in the component version by adding the new remote access specification 84 | as part of the existing local one, using the `globalAccess` attribute. 85 | 86 | The artifact digest is always calculated based on the local access, 87 | but tools may use the information provided by the global access to use technology native ways to access the artifact. 88 | -------------------------------------------------------------------------------- /doc/02-processing/README.md: -------------------------------------------------------------------------------- 1 | # Processing Component Versions (Core) 2 | 3 | This chapter explains how to create and use components. 4 | 5 | * 1.[Referencing](01-references.md#referencing) 6 | * 1.1.[Example](01-references.md#example) 7 | * 2.[Signing](02-signing.md#signing) 8 | * 2.1.[Verification Procedure](02-signing.md#verification-procedure) 9 | * 2.1.1.[Verify with RSA](02-signing.md#verify-with-rsa) 10 | * 2.1.2.[Verify with X509](02-signing.md#verify-with-x509) 11 | * 3.[Normalization](03-signing-process.md#signing-process-and-normalization) 12 | * 3.1.[Artifact Digest](03-signing-process.md#determing-the-artifact-digests) 13 | * 3.2.[Normalization Types](03-signing-process.md#normalization-types) 14 | * 3.3.[Serialization Format](03-signing-process.md#serialization-format) 15 | * 3.4.[Recursive Digest Calculation](03-signing-process.md#recursive-digest-calculation) 16 | * 4.[Example](04-signing-examples.md#examples-for-signing-of-component-versions) 17 | * 4.1.[Simple Component-Version](04-signing-examples.md#simple-component-version) 18 | * 4.2.[Component-Version With Reference](04-signing-examples.md#component-version-with-reference) 19 | * 5.[Component Descriptor Normalization](04-signing-examples.md#component-descriptor-normalization) 20 | * 5.1.[Signing-relevant information in Component Descriptors](04-signing-examples.md#relevant-information-in-component-descriptors) 21 | * 5.1.1.[Access Methods](05-component-descriptor-normalization.md#access-methods) 22 | * 5.1.2.[Labels](05-component-descriptor-normalization.md#labels) 23 | * 5.2.[Exclude Resources from Normalization/Signing](05-component-descriptor-normalization.md#exclude-resources-from-normalizationsigning) 24 | * 5.3.[Generic Normalization Format](05-component-descriptor-normalization.md#generic-normalization-format) 25 | * 5.3.1.[Simple Values](05-component-descriptor-normalization.md#simple-values) 26 | * 5.3.2.[Dictionary](05-component-descriptor-normalization.md#dictionary) 27 | * 5.3.3.[Lists](05-component-descriptor-normalization.md#lists) 28 | * 5.3.4.[Combined example](05-component-descriptor-normalization.md#combined-example) 29 | * 5.3.5.[Empty values](05-component-descriptor-normalization.md#empty-values) 30 | * 6.[Artifact Normalization](06-artifact-normalization.md#artifact-normalization) 31 | * 6.1.[Blob Representation Format for Resource Types](06-artifact-normalization.md#blob-representation-format-for-resource-types) 32 | * 6.2.[Interaction of Local Blobs, Access Methods, Uploaders and Media Types](06-artifact-normalization.md#interaction-of-local-blobs-access-methods-uploaders-and-media-types) 33 | * 6.2.1.[Access Methods](06-artifact-normalization.md#access-methods) 34 | * 6.2.2.[Blob Uploaders](06-artifact-normalization.md#blob-uploaders) 35 | -------------------------------------------------------------------------------- /doc/03-persistence/01-operations.md: -------------------------------------------------------------------------------- 1 | # Model Operations 2 | 3 | This chapter describes the abstract operations an implementation must provide to interact with model elements stored in an OCM persistence. 4 | 5 | ## Abstract Operations defined by the Open Component Model 6 | 7 | The Open Component Model defines abstract operations that must be available to work with a component repository view as interpretation layer on-top of dedicated well-known storage subsystems (like an OCI registry or an S3 blob store). These operations build the first extension point of OCM, which allows to map the OCM functionality onto any blobstore-like storage system. 8 | 9 | A second extension point is the access to artifacts described by a component version. Such access is described by an access specification which is specific for an access method, whose implementation handles the technical access to the artifact content. Implementations for those methods must implement some operations on the access specifications. 10 | 11 | The concrete incarnation of those repository and access method operations depend on the chosen language binding and/or implementation framework use in a dedicated environment. Nevertheless, their behaviour, inputs and outputs can be specified in an abstract manner. 12 | 13 | By defining the data formats used for those operations the interoperability between different implementations is enabled. 14 | 15 | ### Repository Operations 16 | 17 | The Open Component Model specification does not describe a dedicated remotely accessible repository API (like for example the [OCI distribution specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md)). 18 | 19 | The model is intended to be stored in any kind of storage sub system, which is able to store a potentially unlimited number of blobs with an adequate addressing scheme, supporting arbitrary names. 20 | 21 | For example, an OCI repository with a deep repository structure, is suitable to host OCM components (see OCI mapping Scheme). 22 | 23 | On the client side, a suitable implementation or language binding must be available 24 | to work with component information stored in such a storage backend. 25 | 26 | Every such binding must support at least the mandatory set of abstract operations 27 | working with elements of the component model (see below). 28 | 29 | #### Mandatory Operations 30 | 31 | The following operations are mandatory: 32 | 33 | - **`UploadComponentDescriptor(ComponentDescriptor-YAML) error`** 34 | 35 | Persist a serialized form of the descriptor of a component version with its 36 | component identity and version name in way so that it is retrievable again using 37 | this identity. 38 | 39 | - **`GetComponentDescriptor(ComponentId, VersionName) (ComponentDescriptor-YAML, error)`** 40 | 41 | Retrieve a formally persisted description of a component version. 42 | 43 | - **`UploadBlob(ComponentId, VersionName, BlobAccess, MediaType, ReferenceHint) (BlobIdentity, GlobalAccessSpec, error)`** 44 | 45 | Store a byte stream or blob under a namespace given by the component version 46 | identity and return a local blob identity (as string) that can be used to retrieve 47 | the blob, again (together with the component version identity). 48 | 49 | Additionally, a dedicated media type can be used to decide how to internally 50 | represent the artifact content. 51 | 52 | Optionally, the operation may decide to store the blob in dedicated ways according to its media type. For example, an OCI based implementation can represent blobs containing an OCI artifact as regular, globally addressable object. 53 | 54 | A type-specific optional *ReferenceHint* can be passed to guide the operation for generating an identity, if it decided to make the object externally visible. 55 | 56 | If this is the case, an external access specification has to be returned. At least a blob identity or an external access specification has to be returned for not successful executions. 57 | 58 | - **`GetBlob(ComponentId, VersionName, BlobIdentity) (Blob, error)`** 59 | 60 | Retrieve a formerly stored blob, again, using the blob identity provided by the store operation. Technically this should be a stream or the blob content. 61 | 62 | - **`ListComponentVersions(ComponentId) ([]VersionName, error)`** 63 | 64 | List all the known versions of a component specified by its component identity. 65 | 66 | #### Optional Operations 67 | 68 | Optional operations might be: 69 | 70 | - **`DeleteComponentVersion(ComponentId, VersionName) error`** 71 | 72 | To be able to clean up old information, an operation to delete the information 73 | stored for a component version should be available. 74 | 75 | - **`DeleteBlob(ComponentId, VersionName, BlobIndentity) error`** 76 | 77 | It might be useful to provide an explicit delete operation for blobs stored 78 | along with the component version. But the repository implementation 79 | may keep track of used blobs on its own. 80 | 81 | - **`ListComponents(ComponentId-Prefix) ([]ComponentId, error)`** 82 | 83 | List all components in the given identifier namespace. (The structure of a 84 | component id based on hierarchical namespace). 85 | 86 | - **`ListComponentClosure(ComponentId-Prefix) ([]ComponentId, error)`** 87 | 88 | List all components in the given identifier namespace, recursively. 89 | It should not only return component identities, that are direct children, 90 | but traverse the complete subtree. 91 | 92 | ### Access Method Operations 93 | 94 | There must be an implementation for all supported external access methods 95 | according to their specifications. The local access method is mapped to the local blob access provided by the repository. 96 | 97 | They have to support read access, only. At least a media type and stream access for the denoted blob is required. 98 | 99 | - **`.GetMediaType(RepositoryContext, ComponentVersion, AccessSpecification) (string, error)`** 100 | 101 | Provide the media type of the described artifact. It might explicitly be stored as part of the access specification, or implicitly provided by the access method. 102 | 103 | - **`.GetStream(RepositoryContext, ComponentVersion, AccessSpecification) (Byte Stream, error)`** 104 | 105 | Provide access to the blob content described by a dedicated access specification. 106 | -------------------------------------------------------------------------------- /doc/03-persistence/02-mappings.md: -------------------------------------------------------------------------------- 1 | # Mappings for OCM Persistence 2 | 3 | This chapter describes how OCM model elements are mapped to elements of a persistence layer. 4 | 5 | OCM model elements are mapped to various storage technologies. The interoperability layer for a client tool is typically the API of the storage backend. This avoids the need for providing an OCM server infrastructure. 6 | 7 | An implementation of this layer MUST implement this mapping by supporting the [mandatory abstract model operations](./01-operations.md#mandatory-operations). It SHOULD implement the [optional operations](./01-operations.md#optional-operations) too. 8 | 9 | ## Storage Backend Mappings for the Open Component Model 10 | 11 | The OCM specification describes an interpretation layer on-top of well-known storage backend technologies used to store OCM component versions. 12 | 13 | Therefore, for every storage technology a mapping must be defined to ensure interoperability between different OCM implementations. 14 | 15 | These mappings describe: 16 | 17 | - the repository specification type and format used to specify a dedicated repository instance 18 | - the mapping of the OCM elements to the elements provided by the storage technology. 19 | 20 | The mappings are defined as part of the [extensions](../04-extensions/03-storage-backends/README.md) 21 | -------------------------------------------------------------------------------- /doc/03-persistence/README.md: -------------------------------------------------------------------------------- 1 | # OCM Persistence (Core) 2 | 3 | * 1.[Model Operations](01-operations.md#model-operations) 4 | * 2.[Abstract Operations defined by the Open Component Model](01-operations.md#abstract-operations-defined-by-the-open-component-model) 5 | * 2.1.[Repository Operations](01-operations.md#repository-operations) 6 | * 2.1.1.[Mandatory Operations](01-operations.md#mandatory-operations) 7 | * 2.1.2.[Optional Operations](01-operations.md#optional-operations) 8 | * 2.2.[Access Method Operations](01-operations.md#access-method-operations) 9 | * 3.[Mappings for OCM Persistence](02-mappings.md#mappings-for-ocm-persistence) 10 | * 3.1.[Storage Backend Mappings for the Open Component Model](02-mappings.md#storage-backend-mappings-for-the-open-component-model) 11 | -------------------------------------------------------------------------------- /doc/03-persistence/ocm2oci-mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/03-persistence/ocm2oci-mapping.png -------------------------------------------------------------------------------- /doc/04-extensions/00-component-descriptor/README.md: -------------------------------------------------------------------------------- 1 | # Component Descriptor Serialization Formats 2 | 3 | This specification covers two serialization versions for 4 | component descriptors: 5 | 6 | - [v2](v2.md) the version used prior to this specification 7 | - [v3alpha1](v3.md) a serialization format oriented on the Kubernetes manifest structure 8 | -------------------------------------------------------------------------------- /doc/04-extensions/00-component-descriptor/v2.md: -------------------------------------------------------------------------------- 1 | # Component Descriptor Serialization Version v2 2 | 3 | A *Component Descriptor* of version v2 is a [YAML](https://yaml.org/) or 4 | [JSON](https://www.json.org/json-en.html) document according to this 5 | [schema](https://github.com/open-component-model/ocm/blob/main/resources/component-descriptor-v2-schema.yaml). 6 | Additional fields are not allowed. Note that the schemas are maintained in a different [Git repository](https://github.com/open-component-model/ocm/tree/main/resources). 7 | 8 | In serialised form, *Component Descriptors* MUST be UTF-8-encoded. 9 | Either YAML, or JSON MUST be used. If YAML is used as serialisation format, 10 | only the subset of features defined by JSON MUST be used, 11 | thus allowing conversion to a JSON representation. 12 | 13 | YAML is recommended as preferred serialization format. 14 | 15 | YAML permits the usage of comments, and allows different formatting options. 16 | None of those are by contract part of a *Component Descriptor*, 17 | thus implementations may arbitrarily choose to retain or not retain 18 | comments or formatting options. 19 | 20 | The order of attributes is arbitrary, and MUST NOT be relied upon. 21 | 22 | The order of elements in sequences MAY be significant and 23 | MUST be retained in cases where it is significant. 24 | 25 | ## Schema Version 26 | 27 | A *Component Descriptor* document consists of two top level elements: `meta` and `component` 28 | 29 | | Field | Description | 30 | |-----------| ----------- | 31 | | meta | Contains the schema version of the *Component Descriptor* specification. This document defines schema version *v2*. | 32 | | component | Definition of the artifacts which belong to the component version. | 33 | 34 | Example: 35 | 36 | ```yaml 37 | meta: 38 | - schemaVersion: "v2" 39 | component: 40 | ... 41 | ``` 42 | 43 | ## Component 44 | 45 | The `component` field of a *Component Descriptor* has the following fields: 46 | 47 | | Field | Description | 48 | |---------------------| ----------- | 49 | | name | Component name | 50 | | version | Component version | 51 | | repositoryContexts | Locations of the *Component Descriptor* in a transport chain | 52 | | provider | Provider of the component, e.g. a company, organization,... | 53 | | sources | Array of references to sources | 54 | | resources | Array of references to resources | 55 | | componentReferences | Array of references to other *component versions* described by *Component Descriptors* | 56 | | labels | Optional field to add additional information/extensions | 57 | 58 | ### Component Name and Version 59 | 60 | Every *Component Descriptor* has a `name` and `version`, 61 | also called component name and component version. 62 | Name and version are the identifier for a *Component Descriptor* 63 | and the component version described by it. 64 | 65 | ```yaml 66 | meta: 67 | - schemaVersion: "v2" 68 | component: 69 | name: ... 70 | version: ... 71 | ``` 72 | 73 | Component names reside in a global namespace. To avoid name conflicts 74 | component names MUST start with a valid domain name 75 | (as specified by [RFC-1034](https://www.rfc-editor.org/info/rfc1034), 76 | [RFC-1035](https://www.rfc-editor.org/info/rfc1035)) followed by an optional URL path suffix 77 | (as specified by [RFC-1738](https://www.rfc-editor.org/info/rfc1738)). 78 | 79 | Examples are: 80 | 81 | - *github.com* 82 | - *github.com/pathToYourRepo* 83 | 84 | If no URL path suffix is specified, the domain MUST be possessed 85 | by the component owner. If a URL path suffix is specified, 86 | the namespace started by the concatenation of domain and URL path suffix 87 | MUST be controlled by the component owner. 88 | 89 | A component name SHOULD reference a location 90 | where the component’s resources (typically source code, 91 | and/or documentation) are hosted. An example and recommended practise 92 | is using GitHub repository names for components on GitHub like *github.com/pathToYourRepo*. 93 | 94 | Component versions refer to specific snapshots of a component. 95 | A common scenario is the release of a component. Component versions MUST 96 | adhere to a loosened variant of [Semver 2.0.0](https://semver.org/). 97 | 98 | Different to strict SemVer 2.0.0, component versions MAY: 99 | 100 | - have an optional v(ersion) prefix 101 | - omit the third level (patch-level); if omitted, patch-level is implied to equal 0 102 | 103 | The inner elements are described in detail in chapters 104 | [Model Elements](../../01-model/02-elements-toplevel.md) 105 | and [Identifiers](../../01-model/03-elements-sub.md). 106 | 107 | ### Provider 108 | 109 | The provider field may be a simple name or a string containing 110 | a json document describing the provider attributes. 111 | The json document has the following structure: 112 | 113 | | Field | Description | 114 | |-------|---------------------------------------------------------------------| 115 | | name | (required) Provider name | 116 | | labels| list of labels according to the [label specification](../../01-model/07-extensions.md#label-types) | 117 | -------------------------------------------------------------------------------- /doc/04-extensions/00-component-descriptor/v3.md: -------------------------------------------------------------------------------- 1 | # Component Descriptor Serialization Version v3 2 | 3 | The component descriptor V2 is specified in this 4 | [schema](https://github.com/open-component-model/ocm/blob/main/resources/component-descriptor-ocm-v3-schema.yaml). 5 | 6 | Note that the schemas are maintained in a different [Git repository](https://github.com/open-component-model/ocm/blob/main/resources). 7 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/README.md: -------------------------------------------------------------------------------- 1 | # Artifact Types 2 | 3 | The formal type of an artifact uniquely specifies the logical interpretation of an artifact, independent of its concrete technical representation. 4 | Artifacts appear in two flavors in the OCM model, as resources and as sources. They have three main characteristics: 5 | 6 | - content (byte sequence or blob) 7 | - technical format of the blobs (media type) 8 | - semantical meaning 9 | 10 | An artifact type describes the semantic meaning of an artifact, e.g. a Helm chart. The content of a Helm chart might exist in different blob formats, either a directory 11 | tree or an OCI artifact blob, as described by a mime type. The access method always provides the content of an artifact as a blob plus a mime type. 12 | 13 | The definition of an artifact type MUST contain a unique name, the meaning of the content and possible blob formats in form of mime types. 14 | 15 | The following table contains all artifact types defined in the core specification. 16 | 17 | | TYPE NAME | DESCRIPTION | 18 | |-----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| 19 | | [`blob`](blob.md) | Any anonymous untyped blob data | 20 | | [`directoryTree`
`fileSystem`](file-system.md) | Files from a file system (typically provided by a *tar* or *tgz* archive). The mime type of the blob e format | 21 | | [`gitOpsTemplate`](gitops.md) | Filesystem content (tar, tgz) used as GitOps Template, e.g. to set up a git repo used for continuous e using FluxCD | 22 | | [`helmChart`](helmchart.md) | A Helm Chart stored as OCI artifact or as tar blob (`mediaType` tar) | 23 | | [`npmPackage`](npm.md) | A Node Package Manager [npm](https://www.npmjs.com) archive | 24 | | [`ociArtifact`](oci-artifact.md) | A generic OCI artifact following the [open containers image specification](https://github.com/opencontainers/image-spec/blob/main/spec.md) | 25 | | [`ociImage`](oci-image.md) | An OCI image or image list | 26 | | [`executable`](executable.md) | A blob describing an executable program | 27 | | [`sbom`](sbom.md) | A list of ingredients that make up software components () | 28 | 29 | Some additional types are defined, but not part of the core specification. Support is optional, but the list of names is reserved. 30 | 31 | | TYPE NAME |DESCRIPTION | 32 | |--------------------|-------------------------------------| 33 | | [`blueprint`](blueprint.md) | An installation description for the [landscaper](https://github.com/gardener/landscaper) installation | 34 | | [`toiExecutor`](toiexecutor.md) | A toolset for simple installation in the [OCM CLI](https://github.com/open-component-model/ocm/blob/main/docs/reference/ocm_toi.md) installation environment. | 35 | | [`toiPackage`](toipackage.md) | A YAML resource describing the installation for the [OCM CLI](https://github.com/open-component-model/ocm/blob/main/docs/reference/ocm_toi.md) TOI installation. | 36 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/blob.md: -------------------------------------------------------------------------------- 1 | # Blob 2 | 3 | ## Type Name 4 | 5 | **`blob`** 6 | 7 | A blob represents any data without a dedicated logical type. 8 | 9 | ## Format Variants 10 | 11 | Any arbitrary media type is used to define the logical and/or technical format of the byte-stream represented by the blob. 12 | By default the media type `application/octet-stream` can be used for an anoymous byte sequence. 13 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/blueprint.md: -------------------------------------------------------------------------------- 1 | # Blob 2 | 3 | ## Type Name 4 | 5 | **`blueprint`** 6 | 7 | ## Description 8 | 9 | An installation description for the [*landscaper*](https://github.com/gardener/landscaper) installation environment. 10 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/executable.md: -------------------------------------------------------------------------------- 1 | # Executable 2 | 3 | ## Type Name 4 | 5 | **`executable`** 6 | 7 | ## Description 8 | 9 | A blob describing an executable program. The artifact SHOULD use [extraIdentity](../../01-model/03-elements-sub.md#identifiers) 10 | properties to describe the OS architecture and platform the program is intended for 11 | 12 | - `os`: Operating system according to Golang property GOOS 13 | - `architecture`: Architecture according to Golang property GOARCH 14 | 15 | ## Format Variants 16 | 17 | Media Types: 18 | 19 | - `application/octet-stream` 20 | - `application/octet-stream+gzip` 21 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/file-system.md: -------------------------------------------------------------------------------- 1 | # [NAME] 2 | 3 | ## Type Name 4 | 5 | - **`directoryTree`** 6 | 7 | - **`filesystem`** (legacy) 8 | 9 | ## Description 10 | 11 | Filesystem content represented in tar format. 12 | 13 | ## Format Variants 14 | 15 | For content compressed with GNU Zip application/gzip, application/x-gzip, application/x-gtar, and application/x-tgz or application/x-tar+gzip. 16 | 17 | The media type SHOULD be 18 | 19 | - `application/x-tar` 20 | 21 | or for content compressed with GNU Zip 22 | 23 | - `application/x-tgz` 24 | - `application/x-tar+gzip` 25 | - `application/gzip` 26 | - `application/x-gzip` 27 | - `application/x-gtar` 28 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/gitops.md: -------------------------------------------------------------------------------- 1 | # GitOps 2 | 3 | ## Type Name 4 | 5 | **`gitOpsTemplate`** 6 | 7 | ## Description 8 | 9 | Filesystem content (tar, tgz) used as GitOps Template, e.g. to set up a git repo used for continuous e using FluxCD 10 | 11 | ## Format Variants 12 | 13 | It supports the same formats as the [`directoryTree`](file-system.md) type. 14 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/helmchart.md: -------------------------------------------------------------------------------- 1 | # Helm Chart 2 | 3 | ## Type Name 4 | 5 | **`helmChart`** 6 | 7 | ## Description 8 | 9 | A Kubernetes installation resource representing a Helm chart, either stored as OCI artifact or as tar blob. 10 | 11 | ## Format Variants 12 | 13 | - **OCI Artifact** 14 | 15 | A Helm chart might be stored as OCI artifact following the [Artifact Set Archive Format](../common/formatspec.md#artifact-set-archive-format). This format is for example provided by the access method type [`ociArtifact`](../02-access-types/ociartifact.md) 16 | 17 | Media types: 18 | - `application/vnd.oci.image.manifest.v1+tar` 19 | - `application/vnd.oci.image.manifest.v1+tar+gzip` 20 | 21 | The config blob media type described in the OCI manifest MUST be 22 | - `application/vnd.cncf.helm.config.v1+json` 23 | 24 | - **Helm Tar Archive** 25 | 26 | If stored in the Helm tar format (for the filesystem), the tar media type MUST be used. 27 | 28 | Media types: 29 | - `application/vnd.cncf.helm.chart.content.v1.tar` 30 | - `application/vnd.cncf.helm.chart.content.v1.tar+gzip` 31 | 32 | ## Special Support 33 | 34 | There is a dedicated downloader available, that always converts the Helm chart blob into the appropriate filesystem 35 | representation required by Helm when downloading the artifact using the command line interface. 36 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/npm.md: -------------------------------------------------------------------------------- 1 | # npm Package 2 | 3 | ## Type Name 4 | 5 | **`npmPackage`** 6 | 7 | ## Description 8 | 9 | A Node Package Manager ([npm](https://www.npmjs.com)) archive that is located in an npm registry. By default npm packages use the npm public registry at . 10 | 11 | ## Format Variants 12 | 13 | Media Types: 14 | 15 | - `application/x-tar` 16 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/oci-artifact.md: -------------------------------------------------------------------------------- 1 | # OCI Artifact or Artifact Index 2 | 3 | ## Type Name 4 | 5 | **`ociArtifact`** 6 | 7 | ## Description 8 | 9 | A generic OCI artifact following the [open containers image specification](https://github.com/opencontainers/image-spec/blob/main/spec.md). 10 | 11 | ## Format Variants 12 | 13 | When provided as a blob, the [Artifact Set Archive Format](../common/formatspec.md#artifact-set-archive-format) 14 | MUST be used to represent the content of the OCI artifact. 15 | This format can be used to store multiple versions of an OCI repository 16 | in a filesystem-compatible manner. 17 | 18 | Media Types: 19 | 20 | - `application/vnd.oci.image.manifest.v1+tar+gzip`: OCI image manifests 21 | - `application/vnd.oci.image.index.v1+tar.gzip`: OCI index manifests 22 | 23 | ## Special Support 24 | 25 | There is a dedicated uploader available for local blobs. It converts a blob with the media type shown above into a regular OCI artifact in an OCI repository. 26 | 27 | It uses the reference hint attribute of the [`localBlob` access method](../02-access-types/localblob.md) to determine an appropriate OCI repository. If the import target of the OCM component version is an OCI registry, by default, the used OCI repository will be the base repository of the [OCM mapping](../../03-persistence/02-mappings.md#mappings-for-ocm-persistence) with the appended reference hint. 28 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/oci-image.md: -------------------------------------------------------------------------------- 1 | # OCI Image 2 | 3 | ## Type Name 4 | 5 | **`ociImage`** 6 | 7 | ## Description 8 | 9 | This type describes an OCI artifact containing an OCI container image. `ociImage` is a dedicated variant using the container image Media Types 10 | used by OCI registries. 11 | 12 | A general [ociArtifact](oci-artifact.md) describes any kind of content, depending on the media type of its config blob. 13 | 14 | ## Format Variants 15 | 16 | The blob uses the [Artifact Set Archive Format](../common/formatspec.md#artifact-set-archive-format). 17 | 18 | Media Types: 19 | 20 | - `application/vnd.oci.image.manifest.v1+tar` 21 | - `application/vnd.oci.image.manifest.v1+tar+gzip` 22 | 23 | ## Special Support 24 | 25 | There is a dedicated uploader available for local blobs. It converts a blob with the media type shown above into a regular OCI artifact in an OCI repository. 26 | 27 | It uses the reference hint attribute of the [`localBlob` access method](../02-access-types/localblob.md) to determine an appropriate OCI repository. If the import target of the OCM component version is an OCI registry, by default, the used OCI repository will be the base repository of the [OCM mapping](../../03-persistence/02-mappings.md#mappings-for-ocm-persistence) with the appended reference hint. 28 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/sbom.md: -------------------------------------------------------------------------------- 1 | # SBOM 2 | 3 | ## Type Name 4 | 5 | **`sbom`** 6 | 7 | ## Description 8 | 9 | An SBOM is a nested inventory, a list of ingredients that make up software components () 10 | 11 | ## Format Variants 12 | 13 | - **CycloneDX** () 14 | 15 | Media Types: 16 | - `application/vnd.cyclonedx+xml` for CycloneDX files in XML format 17 | - `application/vnd.cyclonedx+json` for CycloneDX files in JSON format 18 | 19 | - **SPDX** () 20 | 21 | Media Types: 22 | - `text/spdx` for SPDX files in tag-value format 23 | - `application/spdx+xml` for SPDX files in RDF format 24 | - `application/spdx+json` for SPDX files in JSON format 25 | - `application/spdx+yaml` for SPDX files in YAML format 26 | 27 | - **SWID** ([NIST](https://csrc.nist.gov/projects/software-identification-swid/guidelines) and [ISO](https://www.iso.org/standard/65666.html)) 28 | 29 | Media Types: 30 | - `application/swid+xml` for SWID files in XML format 31 | 32 | - **Syft** () 33 | 34 | Media Types: 35 | - `application/vnd.syft+json` for Syft generated SBOMs in JSON format 36 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/template.md: -------------------------------------------------------------------------------- 1 | # [NAME] 2 | 3 | ## Type Name 4 | 5 | **`[TYPE]`** 6 | 7 | ## Description 8 | 9 | [DESCRIPTION] 10 | 11 | ## Format Variants 12 | 13 | [FORMAT VARIANTS] 14 | 15 | Media Types: 16 | 17 | - `application/vnd.oci.image.manifest.v1+tar` 18 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/toiexecutor.md: -------------------------------------------------------------------------------- 1 | # `toiExecutor` — Tiny OCM Installer 2 | 3 | TOI is a small toolset on top of the [Open Component Model](../../../README.md). 4 | It provides 5 | a possibility to run images taken from a component version with user 6 | configuration and feed them with the content of this component version. 7 | It is some basic mechanism which can be used to execute simple installation 8 | steps based on content described by the Open Component Model 9 | (see ). 10 | 11 | A TOI executor is YAML resource describing the features of an 12 | TOI executor image. 13 | 14 | It is used by a [`toiPackage` resource](./toipackage.md), which 15 | describes its instantiation for a dedicated installation object. 16 | -------------------------------------------------------------------------------- /doc/04-extensions/01-artifact-types/toipackage.md: -------------------------------------------------------------------------------- 1 | # `toiPackage` — Tiny OCM Installer Package 2 | 3 | TOI is a small toolset on top of the [Open Component Model](../../01-model/01-model.md). 4 | It provides a possibility to run images taken from a component version with user 5 | configuration and feed them with the content of this component version. 6 | It is some basic mechanism which can be used to execute simple installation 7 | steps based on content described by the Open Component Model (see the [TOI documenation](https://github.com/open-component-model/ocm/blob/main/docs/reference/ocm_toi-bootstrapping.md).) 8 | 9 | A TOI package is YAML resource describing the installation handling 10 | for a dedicated software package based on one or more 11 | [`toiExecutor`](toiexecutor.md)s. 12 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/README.md: -------------------------------------------------------------------------------- 1 | # Access Method Types 2 | 3 | Access methods are used to access the content of artifacts described by a component version. Every access method has an access method type. 4 | All access method types are used for **resource** as well as **source** elements. 5 | 6 | The type of the access methods defines the access procedure and the access specification format used to provide the appropriate attributes 7 | required to identify the blob and its location. 8 | 9 | The following access method types are centrally defined: 10 | 11 | | TYPE NAME | DESCRIPTION | 12 | |---------------------------------|-----------------------------------------------------| 13 | | [`localBlob`](localblob.md) | an artifact stored along with the component version | 14 | | [`ociArtifact`](ociartifact.md) | an artifact in a repository of an OCI registry | 15 | | [`ociBlob`](ociblob.md) | a blob in a repository of an OCI registry | 16 | | [`helm`](helm.md) | a Helm chart stored in a Helm Repository | 17 | | [`gitHub`](github.md) | a commit in a GitHub-based Git repository | 18 | | [`s3`](s3.md) | a blob stored in an AWS S3 bucket | 19 | | [`npm`](npm.md) | a NodeJS package stored in an NPM repository | 20 | | [`wget`](wget.md) | a blob stored on an HTTP server | 21 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/github.md: -------------------------------------------------------------------------------- 1 | # gitHub — Git Commit hosted by GitHub 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: gitHub/v1 7 | ``` 8 | 9 | ## Description 10 | 11 | Access to a commit in a Git repository. 12 | 13 | ## Supported Media Types 14 | 15 | - `application/x-tgz`: The artifact content is provided as g-zipped tar archive 16 | 17 | ## Specification Version 18 | 19 | The following versions are supported 20 | 21 | ### v1 22 | 23 | Attributes: 24 | 25 | - **`repoUrl`** *string* 26 | 27 | Repository URL with or without scheme. 28 | 29 | - **`ref`** (optional) *string* 30 | 31 | Original ref used to get the commit from 32 | 33 | - **`commit`** *string* 34 | 35 | The sha/id of the git commit 36 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/helm.md: -------------------------------------------------------------------------------- 1 | # helm — Helm Package in Helm Repository 2 | 3 | *Synopsis:* 4 | 5 | ```text 6 | type: helm[/VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access to a Helm chart in a Helm repository. 13 | 14 | ## Supported Media Types 15 | 16 | - `application/vnd.cncf.helm.chart.content.v1.tar+gzip` 17 | 18 | ## Specification Version 19 | 20 | The following versions are supported 21 | 22 | ### v1 23 | 24 | Attributes: 25 | 26 | - **`helmRepository`** *string* 27 | 28 | Helm repository URL. 29 | 30 | - **`helmChart`** *string* 31 | 32 | The name of the Helm chart and its version separated by a colon. 33 | 34 | - **`caCert`** *string* 35 | 36 | An optional TLS root certificate. 37 | 38 | - **`keyring`** *string* 39 | 40 | An optional keyring used to verify the chart. 41 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/localblob.md: -------------------------------------------------------------------------------- 1 | # localBlob — Blob Hosted in OCM Repository 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: localBlob/[VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access to a resource blob stored along with the component descriptor. 13 | 14 | It's implementation of an OCM repository type how to read the component descriptor. Every repository implementation may decide how and where local blobs are stored, but it MUST provide an implementation for this access method. 15 | 16 | The concrete implementation MUST be provided by the storage backend used to store the component version. All storage backends MUST use the same attribute set. The field `localReference` MAY have a storage backend specific representation for the location information in the backend. It MUST contain the information required by the backend 17 | to access the blob. For example, for an OCI registry backend the `localReference` contains the SHA of the blob used to store the blob as layer in the same OCI artifact 18 | as the component descriptor. 19 | 20 | ## Supported Media Types 21 | 22 | The provided media type is taken from the specification attribute `mediaType`. 23 | 24 | ## Specification Version 25 | 26 | The following versions are supported 27 | 28 | ### v1 29 | 30 | Attributes: 31 | 32 | - **`localReference`** *string* 33 | 34 | Repository type specific location information as string. The value 35 | may encode any deep structure, but typically an access path is sufficient. 36 | 37 | - **`mediaType`** *string* 38 | 39 | The media type of the blob used to store the resource. It may add 40 | format information like `+tar` or `+gzip`. 41 | 42 | - **`referenceName`** (optional) *string* 43 | 44 | This optional attribute may contain identity information used by other repositories to restore some global access with an identity related to the original source. 45 | 46 | For example, an OCI artifact originally referenced using the access method `ociArtifact` is stored during a transport as local artifact. The reference name can then be set to its original repository name. An import step into an OCI repository may then decide to makethis artifact available again as regular OCI artifact using this attribute. 47 | 48 | - **`globalAccess`** (optional) *access method specification* 49 | 50 | If a resource blob is stored locally, the repository implementation may decide to provide an external access information (usable by non OCM-aware tools). For example, an OCI artifact stored as local blob can be additionally stored as regular OCI artifact in an OCI registry. 51 | 52 | This additional external access information can be added using a second external access method specification. 53 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/npm.md: -------------------------------------------------------------------------------- 1 | # npm — Node Package Manager archive 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: npm[/VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access to an NodeJS package in an NPM registry. 13 | 14 | ## Supported Media Types 15 | 16 | - `application/x-tar` 17 | 18 | ## Specification Version 19 | 20 | The following versions are supported 21 | 22 | ### v1 23 | 24 | Attributes: 25 | 26 | - **`registry`** *string* 27 | 28 | Base URL of the NPM registry. 29 | 30 | - **`package`** *string* 31 | 32 | Name of the NPM package. 33 | 34 | - **`version`** *string* 35 | 36 | Version name of the NPM package. 37 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/ociartifact.md: -------------------------------------------------------------------------------- 1 | # ociArtifact — Artifact hosted in OCI Repository 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: ociArtifact[/VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access of an OCI artifact stored in an OCI registry. 13 | 14 | ## Supported Media Types 15 | 16 | - `application/vnd.oci.image.manifest.v1+tar+gzip`: OCI image manifests 17 | - `application/vnd.oci.image.index.v1+tar.gzip`: OCI index manifests 18 | 19 | Depending on the repository appropriate docker legacy types might be used. 20 | 21 | ## Specification Version 22 | 23 | The following versions are supported 24 | 25 | ### v1 26 | 27 | Attributes: 28 | 29 | - **`imageReference`** *string* 30 | 31 | OCI image/artifact reference following the possible docker schemes: 32 | - `/:@` 33 | - `[]/repo path>/:@` 34 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/ociblob.md: -------------------------------------------------------------------------------- 1 | # ociBlob — Blob hosted in OCI Repository 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: ociBlob[/VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access of an OCI blob stored in an OCI repository. 13 | 14 | ## Supported Media Types 15 | 16 | The provided media type is taken from the specification attribute `mediaType`. 17 | 18 | ## Specification Version 19 | 20 | The following versions are supported 21 | 22 | ### v1 23 | 24 | Attributes: 25 | 26 | - **`imageReference`** *string* 27 | 28 | OCI repository reference (this artifact name used to store the blob). 29 | 30 | - **`mediaType`** *string* 31 | 32 | The media type of the blob 33 | 34 | - **`digest`** *string* 35 | 36 | The digest of the blob used to access the blob in the OCI repository. 37 | 38 | - **`size`** *integer* 39 | 40 | The size of the blob 41 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/s3.md: -------------------------------------------------------------------------------- 1 | # s3 — Blob hosted in S3 Blob Store 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: s3[/VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access to a blob stored in an S3 API compatible bucket. 13 | 14 | ## Supported Media Types 15 | 16 | The provided media type is taken from the specification attribute `mediaType`. 17 | 18 | ## Specification Version 19 | 20 | The following versions are supported 21 | 22 | ### v1 23 | 24 | Attributes: 25 | 26 | - **`region`** (optional) *string* 27 | 28 | region identifier of the used store 29 | 30 | - **`bucket`** *string* 31 | 32 | The name of the S3 bucket containing the blob 33 | 34 | - **`key`** *string* 35 | 36 | The key of the desired blob 37 | 38 | - **`mediaType`** *string* 39 | 40 | The media type of the blob used to store the resource. It may add 41 | format information like `+tar` or `+gzip`. 42 | -------------------------------------------------------------------------------- /doc/04-extensions/02-access-types/wget.md: -------------------------------------------------------------------------------- 1 | # wget — Blob hosted on an HTTP server 2 | 3 | ## Synopsis 4 | 5 | ```text 6 | type: wget[/VERSION] 7 | [ATTRIBUTES] 8 | ``` 9 | 10 | ## Description 11 | 12 | Access to a blob stored on an HTTP server. 13 | 14 | ## Supported Media Types 15 | 16 | The provided media type is taken from the specification attribute `mediaType`. 17 | 18 | ## Specification Version 19 | 20 | The following versions are supported 21 | 22 | ### v1 23 | 24 | Attributes: 25 | 26 | - **`url`** *string* 27 | 28 | The url describes from which http server endpoint the resource is downloaded 29 | 30 | - **`mediaType`** (optional) *string* 31 | 32 | The media type of the blob used to store the resource. It may add 33 | format information like `+tar` or `+gzip`. 34 | 35 | - **`header`** (optional) *map\[string\][]string* 36 | 37 | The header describes the http headers to be set in the http request to the server. 38 | 39 | - **`verb`** (optional) *string* 40 | 41 | The verb describes the http verb (also known as http request method) for the http 42 | request. 43 | 44 | - **`body`** (optional) *[]byte* 45 | 46 | The body describes the http body to be included in the request. 47 | 48 | - **`noredirect`** (optional) *bool* 49 | 50 | The noredirect describes whether http redirects should be disabled. 51 | -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/README.md: -------------------------------------------------------------------------------- 1 | # Storage Backend Mappings 2 | 3 | The OCM specification describes an interpretation layer on-top of 4 | well-known storage backend technologies used to store OCM component versions. 5 | 6 | Therefore, for every supported storage technology a dedicated mapping 7 | of OCM model elements to backend elements must be defined to ensure 8 | the interoperability of different OCM implementations. 9 | 10 | These mappings describe: 11 | 12 | - the repository specification [type](../../01-model/07-extensions.md#repository-specification) 13 | and data stricture used to specify a dedicated repository instance 14 | - the mapping of the [OCM elements](../../01-model/02-elements-toplevel.md) 15 | to the elements provided by the storage technology. 16 | - the mapping of the abstract model operations to the appropriate backend 17 | operations 18 | 19 | Mappings for the following technologies are defined: 20 | 21 | | STORAGE BACKEND | DESCRIPTION | 22 | |-----------------|-------------| 23 | | [OCIRegistry](oci.md) | OCM content in OCI registries | 24 | | [FileSystem (CTF)](ctf.md) | OCM content as filesystem structure | 25 | | [FileSystem (Component Archive)](component-archive.md) | Single component version as content as filesystem structure | 26 | | [AWS S3](s3.md) | OCM content in AWS S3 buckets | 27 | 28 | Depending on the used language binding for the OCM model (for example the 29 | [reference implementation in Go](https://github.com/open-component-model/ocm)) 30 | an appropriate binding-specific embedding of this mapping must be provided. 31 | 32 | The following diagram illustrates the embedding of implementation based 33 | extensions (like for the storage backends) into a dedicated language 34 | binding to achieve interoperability among those implementations. 35 | 36 | - *Layer 1* contains the specification of the OCM model. 37 | A dedicated language binding provides an API implementation according to this specification. 38 | This API is then used by consumers requiring access to OCM component versions 39 | in a dedicated programming language (model language binding). 40 | 41 | - *Layer 2* is the abstract extension specification with formats and 42 | operations. Here, it specifies how to embed storage backend 43 | technologies (language independent). 44 | 45 | - *Layer 3* is the abstract specification of the extension mapping for a 46 | dedicated backend technology, describing how extension elements and 47 | operations are mapped to a dedicated backend technology. 48 | Based on this specification an implementation is provided, which 49 | implements the language binding specific incarnation of the extension 50 | API (provided by the implementation of layer 1) to an appropriate 51 | language binding for the backend API. 52 | 53 | - *Layer 4* is finally the API layer of a concrete supported storage 54 | backend. The driver implements the abstract storage backend mapping 55 | supporting the actual model embedding based on a language binding for the 56 | backend storage technology. 57 | 58 |
59 | 60 | ![language bindings](ocmembedding.png) 61 | 62 |
63 | 64 | The specification for layer 1 is described in the [model element specification section](../../01-model/README.md). 65 | The specification of the extension points can be found [here](../../01-model/07-extensions.md). 66 | The storage backend extension specification is [here](../../01-model/07-extensions.md#storage-backends). 67 | 68 | This sections describes the abstract model mapping for the storage backend extensions according to layer 3. 69 | Different implementations (for different language bindings) MUST implement this mapping 70 | to achieve interoperability among different environments. 71 | -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/component-archive.md: -------------------------------------------------------------------------------- 1 | # Component Archive Format 2 | 3 | This section describes how a single component version is stored in a file format. 4 | 5 | This is a special kind of OCM repository storage format capable to host exactly one component version. It is intended to be used during a build process to compose a component version before it is transported into a regular OCM repository. 6 | 7 | ## Specification Format 8 | 9 | To describe a repository context for an OCM repository conforming to this specification the following repository specification format MUST be used. 10 | 11 | ### Synopsis 12 | 13 | ```text 14 | type: ComponentArchive/v1 15 | ``` 16 | 17 | ### Description 18 | 19 | The content of a single OCM Component Version will be stored as Filesystem content. This is a special version of an OCM Repository, which can be used to compose a component version during the build time of a component. 20 | 21 | An OCM repository view will be mapped to a filesystem-based representation according to the [Component Archive Format](../common/formatspec.md#component-archive-format) specification. 22 | 23 | ### Specification Versions 24 | 25 | #### Version `v1` 26 | 27 | The type specific specification fields are: 28 | 29 | - **`filePath`** *string* 30 | 31 | Path in filesystem used to host the repository. 32 | 33 | - **`fileFormat`** (optional) *string* 34 | 35 | The format to use to store content: 36 | - `directory`: stored as directory structure 37 | - `tar`: stored as directory structure in a tar file 38 | - `tgz`: stored as directory structure in a tar file compressed by GNU Zip 39 | 40 | ## Element Mapping 41 | 42 | The component-descriptor is stored as top-level file and local blobs in the `blobs`folder. 43 | 44 | ## Blob Mappings 45 | 46 | This format supports no dedicated blob mappings. Local blobs are always stored as blobs. 47 | 48 | ## Examples 49 | 50 | ```text 51 | component-archive 52 | ├── component-descriptor.yaml 53 | └── blobs 54 | ├── sha.456... (local blob) 55 | └── sha.567... (local blob) 56 | ``` 57 | -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/ctf.md: -------------------------------------------------------------------------------- 1 | # Common Transport Format (CTF) 2 | 3 | This section describes how to store component versions in a file format. 4 | 5 | There is no dedicated file format for OCM content. Instead, the OCI registry mapping is reused to represent OCI content in a filesystem structure. This way the Common Transport Format is defined for general OCI content and can be used to transport OCI as well as OCM content. 6 | 7 | ## Specification Format 8 | 9 | To describe a repository context for an OCM repository conforming to this specification the following repository specification format MUST be used. 10 | 11 | ### Synopsis 12 | 13 | ```text 14 | type: CommonTransportFormat[/VERSION] 15 | [ATTRIBUTES] 16 | ``` 17 | 18 | ### Description 19 | 20 | An OCM repository view will be mapped to a 21 | filesystem-based representation according to the [Common Transport Format](../common/formatspec.md#common-transport-format) specification. 22 | 23 | ### Specification Versions 24 | 25 | Supported specification version is `v1`. 26 | 27 | #### Version `v1` 28 | 29 | The type specific specification fields are: 30 | 31 | - **`filePath`** *string* 32 | 33 | The path in the filesystem used to store the content 34 | 35 | - **`fileFormat`** *string* 36 | 37 | The file format to use: 38 | - `directory`: stored as file hierarchy in a directory 39 | - `tar`: stored as file hierarchy in a TAR file 40 | - `tgz`: stored as file hierarchy in a GNU-zipped TAR file (tgz) 41 | 42 | - **`accessMode`** (optional) *byte* 43 | 44 | Access mode used to access the content: 45 | - 0: write access 46 | - 1: read-only 47 | - 2: create id not existent, yet 48 | 49 | ## Element Mapping 50 | 51 | This format uses the `OCIRegistry` element mapping to map OCM elements to OCI elements. Those elements will then be stored according to the OCI mapping to filesystem content. 52 | 53 | ## Blob Mappings 54 | 55 | This format supports no dedicated blob mappings. 56 | Local blobs are always stored as blobs. 57 | 58 | ## Examples 59 | 60 | ```text 61 | artifact-archive 62 | ├── artifact-index.json 63 | └── blobs 64 | ├── sha.123... (manifest.json) 65 | ├── sha.234... (config.json) 66 | ├── sha.345... (layer 0: component descriptor) 67 | ├── sha.456... (local blob / transport archive of a previously external resource) 68 | └── sha.567... (local blob / transport archive of a previously external resource) 69 | ``` 70 | 71 | The component version appears in the archive-descriptor.json as a tag associated to the digest of the component 72 | descriptor: 73 | 74 | ```json 75 | { 76 | "schemaVersion": 1, 77 | "artifacts": [ 78 | { 79 | "repository": "component-descriptors/>", 80 | "tag": "0.1.0", 81 | "digest": "sha256:123..." 82 | } 83 | ] 84 | } 85 | 86 | ``` 87 | 88 | ### Example of a transport archive containing two artifacts 89 | 90 | ```text 91 | transport-archive 92 | ├── artifact-descriptor.json 93 | └── blobs 94 | ├── sha256.111... (manifest.json of artifact 1) 95 | ├── sha256.222... (config.json of artifact 1) 96 | ├── sha256.333... (layer of artifact 1) 97 | ├── sha256.444... (layer of artifact 1) 98 | ├── sha256.555... (manifest.json of artifact 2) 99 | ├── sha256.666... (config.json of artifact 2) 100 | ├── sha256.777... (layer of artifact 2) 101 | └── sha256.888... (layer of artifact 2) 102 | ``` 103 | 104 | The manifest list in the `artifact-descriptor.json` contains the tags for the two manifests: 105 | 106 | ```json 107 | { 108 | "schemaVersion": 1, 109 | "artifacts": [ 110 | { 111 | "repository": "component-descriptors/", 112 | "tag": "0.1.0", 113 | "digest": "sha256:111..." 114 | }, 115 | { 116 | "repository": "component-descriptors/", 117 | "tag": "0.1.6", 118 | "digest": "sha256:555..." 119 | } 120 | ] 121 | } 122 | ``` 123 | -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/oci.md: -------------------------------------------------------------------------------- 1 | # OCI Registries 2 | 3 | OCM component versions can be stored in OCI registries which are conforming to the [OCI distribution specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md). Additionally, a registry must support a deep repository structure. 4 | 5 | ## Specification Format 6 | 7 | To describe a repository context for an OCM repository conforming to this specification the following repository specification format MUST be used. 8 | 9 | ### Synopsis 10 | 11 | ```text 12 | type: OCIRegistry[/VERSION] 13 | [ATTRIBUTES] 14 | ``` 15 | 16 | ```text 17 | type: ociRegistry[/VERSION] 18 | [ATTRIBUTES] 19 | ``` 20 | 21 | ### Description 22 | 23 | Component descriptors and their artifacts will be mapped to an OCI registry according to the [OCI distribution specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md). 24 | 25 | ### Specification Versions 26 | 27 | Supported specification version is `v1`. 28 | 29 | #### Version `v1` 30 | 31 | The type specific specification fields are: 32 | 33 | - **`baseUrl`** *string* 34 | 35 | OCI registry reference. This is just the hostname, e.g. eu.gcr.io. Any specific repository can be specified using parameter `subPath`. 36 | 37 | - **`subPath`** (optional) *string* 38 | 39 | The base repository name used for the OCM repository. The OCM based artifacts will use this path as repository prefix. An OCI registry may host many OCM repositories with different repository prefixes. 40 | 41 | - **`componentNameMapping`** (optional) *string* 42 | 43 | This attribute describes how component names are mapped to OCI artifact repositories. 44 | There are two flavors: 45 | - `urlPath` (default) the component name is directly used as part of the OCI repository name. 46 | - `sha256-digest` (not used anymore) the digest of the component name is used to limit the length of the OCI repository name. 47 | 48 | ## Element Mapping 49 | 50 | An OCI registry can be used to host multiple OCM repositories. Such an OCM repository is identified by an OCI repository reference. 51 | 52 |
53 | 54 | <*host*>\[`:`<*port*>]{`/`<*repository part*>} 55 | 56 |
57 | 58 | An OCM *component identifier* is mapped to a sub *repository name* prefixed with `component-descriptors/`. The complete repository name is 59 | 60 |
61 | 62 | *<OCI base repository>* `/component-descriptors/` *<component id>* 63 | 64 |
65 | 66 | An OCM *version name* of a component version is mapped to an OCI *tag*. 67 | 68 | The *component version* is represented as OCI *image manifest*. 69 | 70 | This manifest uses a config media type `application/vnd.ocm.software.component.config.v1+json`. 71 | According to the [OCI image specification](https://github.com/opencontainers/image-spec/blob/main/spec.md) this must be a JSON blob. This json file has one defined formal field: 72 | 73 | - **`componentDescriptorLayer`** (required) [*OCI Content Descriptor*](https://github.com/opencontainers/image-spec/blob/main/descriptor.md) 74 | 75 | It references the layer blob containing the component descriptor. The layer 76 | always must be layer 0 of the manifest. It uses the media type 77 | `application/vnd.ocm.software.component-descriptor.v2+yaml+tar` 78 | 79 | The descriptor layer contains a tar archive with at least a single file 80 | with the name `component-descriptor.yaml` containing the component descriptor of the 81 | component version. This file should always be the first file in the tar archive. 82 | 83 | OCM *Local Blobs* are stored in additional OCI *Image Layers*. The local blob 84 | identifier stored in the `localBlob` access specification is the OCI *blob digest* 85 | of the blob. The media type of the blob is the one specified in the 86 | access specification. 87 | 88 | ## Version Mapping 89 | 90 | The Open Component Model supports version names according to [semantic versioning](https://semver.org/). 91 | The tags used to represent versions in the [OCI specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests) do not allow to directly use semantic version names as tags, becase the plus (`+`) character is not supported. Therefore, the open component model version names have to be mapped 92 | to OCI-compliant tag names. 93 | 94 | The followinmg mapping for version is used, here: 95 | 96 | - the optional plus `+` character used to attach build information in semantic versions is mapped to the sequence (`.build-`) 97 | 98 | Mapping tags back to versions uses the following mappings: 99 | 100 | - the last character sequence (`.build-`) is mapped to a plus (`+`) character. 101 | 102 | This way the formal parts of a pre-release of semantic version (separated by dots) are kept 103 | unchanged. The build/metadata suffix of a semantic version is just added as optional last pre-release part, where the prefix `build-` is used to indicate its meaning as metadata suffix. 104 | 105 | ## Blob Mappings 106 | 107 | Local blobs with an OCI artifact media type will implicitly be mapped to a regular 108 | artifact. The *reference hint* provided by the specification of the local access 109 | is used to compose a repository name of the form: 110 | 111 |
112 | 113 | *<oci base repository>* `/` *<reference hint>* 114 | 115 |
116 | 117 | Without a given tag, the provided external access specification (of type `ociArtifact`) 118 | uses a digest based reference. 119 | 120 | Additional blob transformations can be added by registering appropriate blob handlers. 121 | 122 | ## Example 123 | 124 | Given the following component descriptor with a component version consisting of a file and an inline text: 125 | 126 | ```yaml 127 | apiVersion: ocm.software/v3alpha1 128 | kind: ComponentVersion 129 | metadata: 130 | name: github.com/open-component-model/spec-example 131 | provider: 132 | name: github.com/open-component-model 133 | version: 1.0.0 134 | repositoryContexts: 135 | - baseUrl: eu.gcr.io 136 | componentNameMapping: urlPath 137 | subPath: ghcr.io/open-component-model/spec-example 138 | type: OCIRegistry 139 | spec: 140 | resources: 141 | - access: 142 | globalAccess: 143 | digest: sha256:7acd701465611ed8a45d7889b4f3f6ed5e1450ca446f90fd6406cc59ea2baea8 144 | mediaType: text/plain 145 | ref: ghcr.io/open-component-model/spec-example/component-descriptors/github.com/open-component-model/spec-example 146 | size: 26 147 | type: ociBlob 148 | localReference: sha256:7acd701465611ed8a45d7889b4f3f6ed5e1450ca446f90fd6406cc59ea2baea8 149 | mediaType: text/plain 150 | type: localBlob 151 | name: noticeplain 152 | relation: local 153 | type: blob 154 | version: 1.0.0 155 | - access: 156 | globalAccess: 157 | digest: sha256:f5ba8322a580272bbaf93678c48881aa799795bafb9998600655fa669f6ea7bd 158 | mediaType: application/octet-stream 159 | ref: ghcr.io/open-component-model/spec-example/component-descriptors/github.com/open-component-model/spec-example 160 | size: 5266 161 | type: ociBlob 162 | localReference: sha256:f5ba8322a580272bbaf93678c48881aa799795bafb9998600655fa669f6ea7bd 163 | mediaType: application/octet-stream 164 | type: localBlob 165 | name: logo 166 | relation: local 167 | type: blob 168 | ``` 169 | 170 | The OCI image manifest will then have three layers (one for the component-descriptor, one for the logo file and one for the inline text): 171 | 172 | ```yaml 173 | { 174 | "schemaVersion": 2, 175 | "mediaType": "application/vnd.oci.image.manifest.v1+json", 176 | "config": { 177 | "mediaType": "application/vnd.ocm.software.component.config.v1+json", 178 | "digest": "sha256:e63f662a4b600705ed975af69e23fd61d6d68ae1b38d3d3feefbd4df14ce4448", 179 | "size": 201 180 | }, 181 | "layers": [ 182 | { 183 | "mediaType": "application/vnd.ocm.software.component-descriptor.v2+yaml+tar", 184 | "digest": "sha256:0e75813f479e5486985747d6f741ee63d824097c8ee7e48b558bac608bded669", 185 | "size": 3072 186 | }, 187 | { 188 | "mediaType": "text/plain", 189 | "digest": "sha256:7acd701465611ed8a45d7889b4f3f6ed5e1450ca446f90fd6406cc59ea2baea8", 190 | "size": 26 191 | }, 192 | { 193 | "mediaType": "application/octet-stream", 194 | "digest": "sha256:f5ba8322a580272bbaf93678c48881aa799795bafb9998600655fa669f6ea7bd", 195 | "size": 5266 196 | } 197 | ] 198 | } 199 | ``` 200 | 201 | The image configuration is: 202 | 203 | ```yaml 204 | { 205 | "componentDescriptorLayer": { 206 | "mediaType": "application/vnd.ocm.software.component-descriptor.v2+yaml+tar", 207 | "digest": "sha256:0e75813f479e5486985747d6f741ee63d824097c8ee7e48b558bac608bded669", 208 | "size": 3072 209 | } 210 | } 211 | ``` 212 | 213 | If the repo-url is `ghcr.io/open-component-model/spec-example` individual blobs can be accessed using references like 214 | 215 | ```text 216 | ghcr.io/open-component-model/spec-example/component-descriptors/github.com/open-component-model/spec-example@sha256:f5ba8322a580272bbaf93678c48881aa799795bafb9998600655fa669f6ea7bd 217 | ghcr.io/open-component-model/spec-example/component-descriptors/github.com/open-component-model/mymaspec-exampleriadb@sha256:0e75813f479e5486985747d6f741ee63d824097c8ee7e48b558bac608bded669 218 | ghcr.io/open-component-model/spec-example/component-descriptors/github.com/open-component-model/spec-example@sha256:7acd701465611ed8a45d7889b4f3f6ed5e1450ca446f90fd6406cc59ea2baea8 219 | ``` 220 | 221 | Note that these references are contained in the component-descriptor under the `globalAccess` tag in the resources. 222 | -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/ocm2oci-mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/04-extensions/03-storage-backends/ocm2oci-mapping.png -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/ocmembedding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/04-extensions/03-storage-backends/ocmembedding.png -------------------------------------------------------------------------------- /doc/04-extensions/03-storage-backends/s3.md: -------------------------------------------------------------------------------- 1 | # AWS S3 2 | 3 | This specification describes how an OCM repository view is mapped to an S3 blob store. 4 | 5 | ## Specification Format 6 | 7 | To describe a repository context for an OCM repository conforming to this specification the following repository specification format MUST be used. 8 | 9 | ### Synopsis 10 | 11 | ```text 12 | type: S3[/VERSION] 13 | [ATTRIBIUTES] 14 | ``` 15 | 16 | ### Description 17 | 18 | Artifact namespaces/repositories of the API layer will be mapped to an S3 bucket. 19 | 20 | ### Specification Versions 21 | 22 | Supported specification version is `v1`. 23 | 24 | #### Version `v1` 25 | 26 | The type specific specification fields are: 27 | 28 | - **`bucketURL`** *string* 29 | 30 | S3 bucket reference 31 | 32 | ## Element Mapping 33 | 34 | An *OCM repository* is mapped to an *S3 bucket*. 35 | 36 | The component id is mapped to an object path below this bucket, followed by a namespace component `__versions__`. 37 | 38 | The OCM *component version* is stored below an additional folder with the version name of the component version. 39 | 40 | All artifacts belonging to a component version are stored as blobs below this folder. 41 | 42 | The OCM *component descriptor* of a component version is stored with the name `component-descriptor.yaml` in [YAML](https://yaml.org/spec/) format. 43 | 44 | Local blobs are stored as additional blobs in the same folder. The blob identity is the name of the blob object in this folder. 45 | 46 | The name should be derived from the digest of the blob. 47 | 48 | For example: 49 | 50 | ```text 51 | └── bucket 52 | ├── 53 | │   └── __versions__ 54 | │   └── 55 | │   ├── component-descriptor.yaml 56 | │   ├── 57 | │   └── 58 | └── github.com 59 | └── gardener 60 | └── external-dns-management 61 | └── __versions__ 62 | └── 1.0.0 63 | ├── component-descriptor.yaml 64 | └── sha256.1d4382e73dc767efc4f3cf43cb970d09104ea26301fc1495244c11e2ad45639e 65 | 66 | ``` 67 | 68 | ## Blob Mapping 69 | 70 | Because the base repository is a pure blob store, no dedicated blob mappings are required. 71 | -------------------------------------------------------------------------------- /doc/04-extensions/04-algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | 3 | This chapter lists the different algorithms used within the component model. 4 | 5 | | ALGORITHM KIND | DESCRIPTION | 6 | |----------------|-------------| 7 | | [Artifact Normalization](artifact-normalization-types.md) | Logical digest calculation for artifact blobs | 8 | | [Digest Algorithms](digest-algorithms.md) | Kind of used digest | 9 | | [Label Merge Algorithms](label-merge-algorithms.md) | Algorithms to merge label values during delta transport | 10 | | [Component Descriptor Normalization Algorithms](component-descriptor-normalization-algorithms.md) | Algorithms used to normalize component descriptors for signing | 11 | | [Signing Algorithms](signing-algorithms.md) | Algorithms used to sign a normalized component version | 12 | -------------------------------------------------------------------------------- /doc/04-extensions/04-algorithms/artifact-normalization-types.md: -------------------------------------------------------------------------------- 1 | # Artifact Normalization Types 2 | 3 | The following algorithms are defined: 4 | 5 | - `EXCLUDE-FROM-SIGNATURE`: Blob content is ignored for the signing process. 6 | 7 | This is a possibility for referencing volatile artifact content. 8 | 9 | - `genericBlobDigest/v1` (*default*): Blob byte stream digest 10 | 11 | This is the default algorithm. It just uses the blob content 12 | provided by the access method of an OCM artifact to calculate the digest. 13 | It is always used, if no special digester is available for an artifact type. 14 | 15 | - `ociArtifactDigest/v1`: OCI manifest digest 16 | 17 | This algorithm is used for artifact blobs with the media type of an OCI artifact. 18 | It just uses the manifest digest of the OCI artifact. 19 | -------------------------------------------------------------------------------- /doc/04-extensions/04-algorithms/component-descriptor-normalization-algorithms.md: -------------------------------------------------------------------------------- 1 | # Normalization Algorithms 2 | 3 | Currently the there are two different normalizations defined: 4 | 5 | - `jsonNormalisationV1`: This is a legacy format, which depends on the format of the 6 | component descriptor 7 | - `jsonNormalisationV2`: This is the new format. which is independent of the 8 | chosen representation format of the component descriptor. 9 | 10 | The normalization process is divided into two steps: 11 | 12 | - *extraction of the signature relevant information from the component descriptor* 13 | 14 | The result is basically a JSON object, which decsribed the relevant information. 15 | 16 | - *normalization of the resulting JSON object* 17 | 18 | Here, the object is serialized to a unique and reproducable byte sequence, which is finally used to determine the digest. 19 | 20 | There are two such normalization methods: 21 | - `jsonNormalisationV1` 22 | - `jsonNormalisationV2` 23 | 24 | ## `jsonNormalisationV1` 25 | 26 | The `JsonNormalisationV1` serialization format is based on the serialization format of the component descriptor. 27 | It uses an appropriate JSON object containing the relevant fields as contained in the component descriptors's serialization. 28 | The format version fields are included. Therefore, the normalized form is depending on the chosen serialization format. 29 | Changing this format version would result in different digests. 30 | The resulting JSON object is serialized with the [OCM specific scheme](../../02-processing/05-component-descriptor-normalization.md#generic-normalization-format) 31 | 32 | ## `jsonNormalisationV2` 33 | 34 | `JsonNormalisationV2` strictly uses only the relevant component descriptor 35 | information according to the field specification. It is independent of the serialization format used to store the component decsriptor in some storage backend. Therefore, the calculated digest is finally independent of the serialization format chosen for storing the component descriptor in a storage backend. It uses a standard scheme according to [RFC8785 (JCS)](https://www.rfc-editor.org/rfc/rfc8785) 36 | 37 | Relevant fields and their mapping to the normalized data structure for `JsonNormalisationV2` are: 38 | 39 | - Component Name: mapped to `component.name` 40 | - Component Version: mapped to `component.version` 41 | - Component Labels: mapped to `component.labels` 42 | - Component Provider: mapped to `component.provider` 43 | - Resources: mapped to `component.resources`, if no resource is present, an empty list is enforced 44 | - Sources: mapped to `component.sources`, if no source is present, an empty list is enforced 45 | - References: mapped to `component.references`, if no reference is present, an empty list is enforced 46 | -------------------------------------------------------------------------------- /doc/04-extensions/04-algorithms/digest-algorithms.md: -------------------------------------------------------------------------------- 1 | # Digest Algorithms 2 | 3 | Digest algorithms describe the way digests are calculated from a byte stream. 4 | 5 | The following digest algorithms are defined: 6 | 7 | - `SHA-256` 8 | - `SHA-512` 9 | - `NO-DIGEST` (only used together with artifact normalization type `EXCLUDE-FROM-SIGNATURE`) 10 | -------------------------------------------------------------------------------- /doc/04-extensions/04-algorithms/label-merge-algorithms.md: -------------------------------------------------------------------------------- 1 | # Label Merge Algorithms 2 | 3 | There is a set of globally defined standard algorithms: 4 | 5 | - `default` just decide for one side or reject the transfer. 6 | 7 | It used the following configuration fields: 8 | 9 | - `overwrite` *string* specify the behaviour in case of a conflict. The following configuration values are possible: 10 | 11 | - `none` reject changes 12 | 13 | - `local` keep the local value found in the target 14 | 15 | - `inbound` overwrite the local value with the transferred values. THis is the default for this merge algorithm 16 | 17 | - `simpleListMerge` just merge the list. 18 | 19 | The resulting value will contain all the entries of 20 | 21 | the inbound and the local version. 22 | 23 | - `simpleMapMerge` just merge the elements of a map. 24 | 25 | The resulting value will contain all the entries of 26 | 27 | the inbound and the local version. In case of a 28 | 29 | conflict the entry is merged according the selected overwrite mode ( default `none`) 30 | 31 | The following configuration values are possible: 32 | 33 | - `overwrite` *string*: conflict resolution hint (see `default`). 34 | 35 | - `entries` [*merge spec*](../../01-model/07-extensions.md#label-merge-algorithms) 36 | merge specification to be used for conflicting entries. 37 | 38 | If no overwrite mode is selected AND the `entries` field is given, 39 | conflicting entries will be merged with the specified merge specification. 40 | Otherwise, the default resolution is `none` 41 | 42 | - `simplemMapListNerge` merge maps used as list entries. 43 | 44 | If a list contains map entries which feature an identity, 45 | list entries with the same identity can be merged. 46 | 47 | This algorithm uses a key field in the maps to detect their identity. 48 | 49 | The following configuration values are possible: 50 | 51 | - `overwrite` *string*: conflict resolution hint (see `default`). 52 | 53 | - `entries` [*merge spec*](../../01-model/07-extensions.md#label-merge-algorithms) 54 | merge specification to be used for conflicting entries. 55 | 56 | If no overwrite mode is selected AND the `entries` field is given, 57 | conflicting entries will be merged with the specified merge specification. 58 | Otherwise, the default resolution is `none`. 59 | 60 | All algorithms supporting cascading of merge algorithms for their element (in the meaning defined by the algorithm) SHOULD offer such a merge specification field complying to the standard fields of a merge specification. It is a good practice to use an unset `overwrite` conflict resolution field to enable the cascading and support the other standard options, also. 61 | -------------------------------------------------------------------------------- /doc/04-extensions/04-algorithms/signing-algorithms.md: -------------------------------------------------------------------------------- 1 | # Signature Algorithms 2 | 3 | Signing a component descriptor requires a hash of the normalized component descriptor, 4 | which will the be signed with the selected signing algorithm. 5 | 6 | ## RSA 7 | 8 | *Algorith Name:* `RSASSA-PKCS1-V1_5` 9 | 10 | After the digest for the normalised component descriptor is calculated, it can be signed using RSASSA-PKCS1-V1_5 11 | as signature.algorithm. The corresponding signature is stored hex encoded in `signature.value` with a `mediaType` of 12 | `application/vnd.ocm.signature.rsa`. 13 | -------------------------------------------------------------------------------- /doc/04-extensions/README.md: -------------------------------------------------------------------------------- 1 | # Extensions 2 | 3 | The core specification does not rely on a fixed set of certain fields. 4 | However, the specification defines a set of known values for certain types 5 | listed in the following sections. These sets can be extended by new specification versions, 6 | addendums or for customer-specific environments. 7 | 8 | ## Table of Content 9 | 10 | * 1 [Artifact Types](01-artifact-types/README.md) 11 | * 1.1 [blob](01-artifact-types/blob.md) 12 | * 1.2 [directoryTree, fileSystem](01-artifact-types/file-system.md) 13 | * 1.3 [gitOpsTemplate](01-artifact-types/gitops.md) 14 | * 1.4 [helmChart](01-artifact-types/helmchart.md) 15 | * 1.5 [npmPackage](01-artifact-types/npm.md) 16 | * 1.6 [ociArtifact](01-artifact-types/oci-artifact.md) 17 | * 1.7 [ociImage](01-artifact-types/oci-image.md) 18 | * 1.8 [executable](01-artifact-types/executable.md) 19 | * 1.9 [sbom](01-artifact-types/sbom.md) 20 | * 2 [Access Method Types](02-access-types/README.md) 21 | * 2.1 [localBlob](02-access-types/localblob.md) 22 | * 2.2 [ociArtifact](02-access-types/ociartifact.md) 23 | * 2.3 [ociBlob](02-access-types/ociblob.md) 24 | * 2.4 [helm](02-access-types/helm.md) 25 | * 2.5 [gitHub](02-access-types/github.md) 26 | * 2.6 [s3](02-access-types/s3.md) 27 | * 2.7 [npm](02-access-types/npm.md) 28 | * 2.8 [wget](02-access-types/wget.md) 29 | * 3 [Storage Backend Mappings](03-storage-backends/README.md) 30 | * 3.1 [OCIRegistry](03-storage-backends/oci.md) 31 | * 3.2 [FileSystem (CTF)](03-storage-backends/ctf.md) 32 | * 3.3 [FileSystem (Component Archive)](03-storage-backends/component-archive.md) 33 | * 3.4 [AWS S3](03-storage-backends/s3.md) 34 | * 4 [Algorithms](04-algorithms/README.md) 35 | * 4.1 [Artifact Normalization](04-algorithms/artifact-normalization-types.md) 36 | * 4.2 [Digest Algorithms](04-algorithms/label-merge-algorithms.md) 37 | * 4.3 [Label Merge Algorithm](04-algorithms/digest-algorithms.md) 38 | * 4.4 [Component Descriptor Normalization Algorithms](04-algorithms/component-descriptor-normalization-algorithms.md) 39 | * 4.5 [Signing Algorithms](04-algorithms/signing-algorithms.md) 40 | -------------------------------------------------------------------------------- /doc/04-extensions/common/formatspec.md: -------------------------------------------------------------------------------- 1 | 2 | # *Common Transport Format* 3 | 4 | The *Common Transport Format* describes a file system structure that can be 5 | used for the representation of [content](https://github.com/opencontainers/image-spec) 6 | of an OCI repository. 7 | 8 | It is used to describe an OCI repository structure. Therefore, it can be used 9 | to describe a subset of repositories of an OCI registry with a subset of 10 | artifacts, that can then be imported again into any OCI registry. 11 | 12 | It is a directory containing 13 | 14 | - **`artifact-index.json`** *[Artifact Index](#artifact-index)* 15 | 16 | This JSON file describes the contained artifact (versions). 17 | 18 | - **`blobs`** *directory* 19 | 20 | The *blobs* directory contains the blobs described by the 21 | *artifact index* as a flat file list. These are layer blobs or artifact 22 | blobs for the artifact descriptors. Every file has a filename according 23 | to its [digest](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests). 24 | Hereby the algorithm separator character is replaced by a dot ("."). 25 | Every file SHOULD be referenced, directly or indirectly, in the artifact 26 | descriptor by a 27 | [descriptor according the OCI Image Specification](https://github.com/opencontainers/image-spec/blob/main/descriptor.md). 28 | 29 | The artifact index describes the OCI manifests (image manifests and index 30 | manifests), which refer to further non-manifest blobs. 31 | Files not referenced by the artifacts described by the index are ignored. 32 | 33 | This format might be used in various technical forms: as structure of an 34 | operating system file system, a virtual file system or as content of 35 | an archive file. The descriptor SHOULD be the first file if stored in an archive. 36 | 37 | ## *Artifact Index* 38 | 39 | The *Artifact Index* is a JSON file describing the artifact content in 40 | a file system structure according to this specification. 41 | 42 | ### *Artifact Index* Property Descriptions 43 | 44 | It contains the following properties. 45 | 46 | - **`schemaVersion`** *int* 47 | 48 | This REQUIRED property specifies the index schema version. 49 | For this version of the specification, this MUST be `1`. The value of this 50 | field will not change. This field MAY be removed in a future version of the 51 | specification. 52 | 53 | - **`index`** *[artifact](#artifact-property-descriptions)* 54 | 55 | ### *Artifact* Property Descriptions 56 | 57 | An artifact consists of a set of properties encapsulated in key-value fields. 58 | 59 | The following fields contain the properties that constitute an *Artifact*: 60 | 61 | - **`repository`** *string* 62 | 63 | This REQUIRED property is the *repository* name of the targeted artifact described by the 64 | *Common Transport Format*, conforming to the requirements outlined in the 65 | [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md). 66 | 67 | - **`digest`** *string* 68 | 69 | This REQUIRED property is the *digest* of the targeted artifact blob in the targeted 70 | artifact set, conforming to the requirements outlined in 71 | [Digests](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests). 72 | Retrieved content SHOULD be verified against this digest when consumed via 73 | untrusted sources. 74 | 75 | - **`tag`** *string* 76 | 77 | This optional property is the *tag* of the targeted artifact, conforming to 78 | the requirements outlined in the 79 | [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md). 80 | 81 | There might be multiple entries in the artifact list referring to the same artifact 82 | with different tags. But all used tags for a repository must be unique. 83 | 84 | ## *Artifact Set Archive* Format 85 | 86 | The *Artifact Set Archive* Format describes a file system structure that can be 87 | used for the representation of a dedicated set of [artifact versions](https://github.com/opencontainers/image-spec) 88 | of an OCI registry for the same OCI repository. 89 | 90 | An artifact set can be exported from an OCI repository and imported into another 91 | OCI repository, it only contains artifacts and tags from a single repository. 92 | 93 | In the archive form the artifact set descriptor SHOULD be the first file. 94 | 95 | The file structure is a directory containing 96 | 97 | - **`artifact-set-descriptor.json`** *[oci image index](https://github.com/opencontainers/image-spec/blob/main/image-index.md)* 98 | 99 | This JSON file describes the contained artifact (version). It MUST be an index manifest. 100 | It MUST describe all *[artifacts](https://github.com/opencontainers/image-spec/blob/main/manifest.md)* 101 | that should be addressable. 102 | 103 | - **`blobs`** *directory* 104 | 105 | The *blobs* directory contains the blobs described by the artifact set descriptor 106 | as a flat file list. Every file has a filename according to its 107 | [digest](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests). 108 | Hereby the algorithm separator character is replaced by a dot ("."). 109 | Every file SHOULD be referenced in the artifact descriptor by a 110 | [descriptor according the OCI Image Specification](https://github.com/opencontainers/image-spec/blob/main/descriptor.md). 111 | 112 | Files not referenced by the artifacts described by the index are ignored. 113 | 114 | The artifact set index describes the manifest entries that should be registered 115 | via the manifest endpoint according to the distribution spec. 116 | 117 | ### Extension Models 118 | 119 | Any artifact described by this format is addressable only by digests. 120 | The entries in the index are intended to be registered via the manifest 121 | endpoint according to the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec). 122 | 123 | Additionally this specification describes two special annotations, that can be 124 | set for any described artifact in the annotations attribute of the manifest 125 | list entries: 126 | 127 | - **`software.ocm/tags`** 128 | 129 | This annotation can be used to describe a comma-separated list of tags. 130 | that should be added for this index entry, when imported into an OCI registry. 131 | 132 | - **`software.ocm/type`** 133 | 134 | This annotation can be used for some additional type information. 135 | 136 | For the annotations of the index itself the following keys are defined: 137 | 138 | - **`software.ocm/main`** *digest* 139 | 140 | This annotation describes the digest of the main artifact of the set, if used 141 | as blob format for an artifact 142 | 143 | This way the format can be used to attach elements according to various extension 144 | models for the OCI specification: 145 | 146 | - *[cosign](https://github.com/sigstore/cosign)* 147 | 148 | For *cosign* additional signatures are represented as dedicated artifacts 149 | with special tags establishing the relation to the original artifact they 150 | refer to by deriving the tag from the digest of the related object. 151 | 152 | This is supported by this format by providing a possibility to describe 153 | additional tags by an annotation in the index 154 | 155 | - [*ORAS*](https://github.com/oras-project/artifacts-spec) 156 | 157 | Here a new third top-level manifest type is introduced, that can be 158 | stored via the manifest endpoint of the distribution spec. No additional 159 | tags are required, the relation to the annotated object is established 160 | by a dedicated digest based field. Those artifacts can directly be 161 | described by this format. But language bindings basically have to support 162 | this additional type. 163 | 164 | # *Component Archive Format* 165 | 166 | This is a special filesystem based format to store the content of 167 | a single component version. It is intended to be used during a 168 | build process to incrementally compose a component version. 169 | Once finished it can be transfered to a regular OCM repository. 170 | 171 | It is a directory containing 172 | 173 | - **`component-descriptor.yaml`** *YAML file* 174 | 175 | This yaml is the serialized form of a [component descriptor](../../01-model/01-model.md#components-and-component-versions). 176 | 177 | - **`blobs`** *directory* 178 | 179 | The *blobs* directory contains the local blobs described by the 180 | *component descriptor* as a flat file list. Typically, every 181 | file has a filename according to its [digest](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests). 182 | Hereby the algorithm separator character is replaced by a dot ("."). 183 | Every file SHOULD be referenced, directly or indirectly, in the 184 | component descriptor by a 185 | [`localBlob` access specification](../../04-extensions/01-artifact-types/blob.md). The `localReference` value is the file name of the blob file in the `blobs` directory. 186 | 187 | This format might be used in various technical forms: as structure of an 188 | operating system file system, a virtual file system or as content of 189 | an archive file. The descriptor SHOULD be the first file if stored in an 190 | archive. 191 | -------------------------------------------------------------------------------- /doc/05-guidelines/01-transport.md: -------------------------------------------------------------------------------- 1 | # Transport 2 | 3 | In some scenarios it is required to transfer artifacts to a different location. For example: 4 | 5 | * deployments have to be performed in isolated environments without Internet access 6 | * replication between locations in different regions or environments, sometimes far away. 7 | 8 | It is required to transfer delivered artifacts consistently. 9 | 10 | The model provided by OCM can be used to create a transport tool being able to transfer the complete closure of a component version from one environment to another. 11 | 12 | To support this, a component version includes the access information for the described artifacts. If no applicable storage system for an artifact type according to its access method is available it can be stored as local blob along with the component descriptor. 13 | 14 | The descriptor stored in the target repository has to be adapted accordingly to reflect the new ocal location. In this way OCM allows to provide modifiable access information for artifacts. 15 | 16 | The transport target might even be an archive or filesystem. This enables the transport of OCM content into fenced environments via data storage media (e.g USB stick). 17 | 18 | A transport might be done with various options: 19 | 20 | * *recursive or non-recursive* 21 | 22 | If a component version should be transferred into a local environment all referenced component versions have to be transferred too. This is called a recursive transport. 23 | 24 | * *by-value or by-reference* 25 | 26 | It is possible to transfer component version as they are. This means, only the 27 | component version meta information including the component descriptor and the local blobs are transferred, but externally referenced artifacts are kept at their current location. If a transport is done by-value the content of the external artifacts is transferred too. 28 | By default, the content is transformed to a blob representation which is stored as local blob along with the component descriptor in the target repository. Optional artifacts can be imported into its native repository format. So by default, OCI artifacts SHOULD be transferred to regular OCI artifacts if the target OCM repository is an OCI registry. In this way external tools can reference them as before (e.g. an image reference). 29 | 30 | ## Kinds of Transports 31 | 32 | A transport of a component version from one component repository into another one can be done in several ways: 33 | 34 | * directly from an OCM repository to another one: To support transport by value requires the availability of a blob state in the target environment. 35 | * indirectly using an intermediate file based format: This format must be capable to store blobs that have to be transported side-by-side with the component descriptors. In this format the component descriptor must be capable to describe the access to those locally stored blobs. 36 | 37 | To simplify and unify the handling of those two scenarios, and generally the handling of blobs in various environments, a component repository must also include support for storing blobs under the identity of the component descriptor. A repository implementation may forward this task to a predefinied other blob store or handle this part of the API in its own way. 38 | 39 | This enables: 40 | 41 | * a simple usage of a component repository to store any content without the need of always requiring other external stores for (possibly specific types of) resources, e.g. for storing simple configuration data along with the component descriptor. 42 | * providing a respository implementation for file system formats that can be used transparently by component tools. 43 | * the usage of a minimal repository environment on the target side of a transport by just using a dedicated component repository. 44 | 45 | Therefore, *Component Repositories* MUST provide the possibility to store technical artifacts together with the component descriptors in the component repository itself (as *local blobs*). The general access method type `localBlob` MUST be supported by all repository implementations. This allows packing all component versions with their technical artifacts in a *Component Repository* as a completely self-contained package. 46 | 47 | As example, assume some component needs additional configuration data stored in some YAML file. If in any landscape of your transport chain there is only an OCI registry available to store content, you need to define a format how to store such a YAML file in the OCI registry. With *local blobs* you could just upload the file into the *Component Repository*. 48 | -------------------------------------------------------------------------------- /doc/05-guidelines/02-contract.md: -------------------------------------------------------------------------------- 1 | # Model Contract 2 | 3 | The plain Open Component Model itself offers a solid foundation, and its true potential shines when complemented by various tools that interact with the model, enhancing its overall value. 4 | 5 | A first example of such a tool is a transport tool. It uses the access information of resources contained in a component version to copy software artifacts from one environment into another. Resource locations will be potentially adapted for the component versions in the target environment. 6 | 7 | Another example could be a deployment tool using component versions to determine the artifacts to be deployed into a target environments. 8 | 9 | Such tools are out-of-scope for the OCM specification. Nevertheless, they must interact with the content described by the Open Component Model. There must be a contract between the model and the way tools interact with the model. 10 | 11 | This contract consists of two parts: 12 | 13 | - All content required to deploy and install software described by a component version must be included as resources in this component version. 14 | - All resource locations (e.g. image locations) used in a runtime environment must be taken from the access information provided by the used component versions. 15 | 16 | This has various consequences especially for deployment environments, but basically for all tools working with the component model and even the component model itself: 17 | 18 | - Deployment descriptions MUST be part of a component version. They have to be stored as additional resources with an appropriate (tool/technology specific) artifact type. There are too many deployment technologies to define them centrally. Deploment descriptions therefore use extensions. 19 | - Those descriptions MUST use descriptive elements of the component model to locate and access artifacts. It is not allowed to use explicit, absolute or global direct artifact locations. 20 | - A component version MUST include all resources, either directly contained in the component version or by referring to other component versions using references. References can contain other references resulting in a graph. To avoid the need of describing always complete closed sets of artifacts in a single component version the model offers the [component reference/aggregation feature](../02-processing/01-references.md). 21 | - The artifacts must be resolvable in the context of the component version containing this description as artifact. See also [relative artifact references](../02-processing/01-references.md#relative-artifact-references) 22 | 23 | ## Example: Helm deployment 24 | 25 | As an example of a deployment technology, we use the [helm deployment system](https://helm.sh/) for Kubernetes. 26 | 27 | A helm chart describes Kubernetes resources, which are templated using values provided when deploying a chart. 28 | 29 | Typically, a helm chart contains container image references (often provided as a default value for a template variable). Using such a default value violates the above contract: the location of resources must be taken from the component version describing the deployment (the helm chart). This step is also called *image localization*: All images in a chart must be templated to be able to specify the concrete values by a deployment configuration. An OCM conformant deployment tool must provide the values from the resources of a component version. 30 | 31 | A tool used to deploy a component version with helm therefore requires several resources: 32 | 33 | - all the images required for the helm chart 34 | - the helm chart 35 | - a helm specific description containig a mapping of value names to image locations of the component version. 36 | 37 | The OCM-compliant deploy tool (ocm-helm-adapter) must: 38 | 39 | - take the helm chart as a resource from the component version 40 | - know the format of the mapping description and generate the values for helm. 41 | 42 | The deploy tool can then call the native helm command using the helm chart location from the component version and the generated helm values. 43 | 44 |
45 | OCM and Helm Deployments 46 |
47 | 48 | ### Example: Indirect Deployments 49 | 50 | A deployed image may contain code to deploy pods to a Kubernetes cluster (for example, a Kubernetes operator managing some service instances). These image locations must also be taken from the component version requiring an additional indirection. For an OCM-compliant deployment, the executable of the image must accept some argument or configuration to pass these locations at runtime. The necessary mapping from resources of a component version to the configuration of the deployer executable must again be described in the description resource and processed by the adapter to generate the target configuration. 51 | 52 |
53 | OCM and Helm Deployments with indirect Deployments 54 |
55 | -------------------------------------------------------------------------------- /doc/05-guidelines/03-references.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | ## Relative Artifact References 4 | 5 | A composite, consisting of an artifact identity and a sequence of reference identities is called relative *Source Reference* or *Resource Reference*. It can be used in artifacts described by a component version to refer to other artifacts described by the same component version. 6 | 7 | *Example:* 8 | 9 | Component Version: `A:1.0.0`: 10 | 11 | ```yaml 12 | apiVersion: ocm.software/v3alpha1 13 | kind: ComponentVersion 14 | metadata: 15 | name: github.com/acme/A 16 | version: 1.0.0 17 | ... 18 | spec: 19 | resources: 20 | name: DEPLOYER 21 | type: mySpecialDeploymentDescription 22 | ... 23 | - access: 24 | ... 25 | references: 26 | - name: ref_to_b 27 | componentName: github.com/acme/B 28 | version: 1.0.0 29 | ... 30 | ``` 31 | 32 | Here we define a component version `A` with a resource having a custom type. Furthermore it references a component `B` and names this reference `ref_to_b`. 33 | 34 | Then we have a second component `B:1.0.0` with on OCI image resource: 35 | 36 | ```yaml 37 | apiVersion: ocm.software/v3alpha1 38 | kind: ComponentVersion 39 | metadata: 40 | name: github.com/acme/B 41 | version: 1.0.0 42 | ... 43 | spec: 44 | resources: 45 | name: IMAGE 46 | type: ociImage 47 | ... 48 | - access: 49 | ... 50 | ... 51 | ``` 52 | 53 | The deployment description contained in `A` has a proprierty format unnknown to OCM. It is used by some deployment tooling interpreting this description. For example it may have the following content: 54 | 55 | ```yaml 56 | # Deployment description in 'mySpecialDeploymentDescription' format: 57 | ... 58 | deploymentImages: 59 | - resource: 60 | name: IMAGE 61 | referencePath: 62 | - name: ref_to_b 63 | ``` 64 | 65 | This description contains a resource reference indicating to use the resource named `IMAGE` of some component version. As the description is part of component version `A:1.0.0`, `content` is resolved by checking the named references in `A`. The reference named `ref_to_b` refers to component `B:1.0.0`. Looking up the resources of `B` a resource named `IMAGE` can be found. 66 | 67 | This mechanism can be also used for multiple level of indirections: 68 | 69 | ```yaml 70 | # Deployment description in 'mySpecialDeploymentDescription' format: 71 | ... 72 | deploymentImages: 73 | - resource: 74 | name: IMAGE 75 | referencePath: 76 | - name: ref_to_b 77 | name: ref_to_c 78 | name: ref_to_d 79 | ``` 80 | 81 | In this case component `A` would have a reference `ref_to_b` as before. `B` would then contain another reference named `ref_to_c` pointing to another component, e.g. `C:1.0.0`. `C` would contain a reference named `ref_to_d` pointing, e.g. to `D:1.0.0`. `D` then would contain a resource named `IMAGE`. 82 | 83 | This kind of relative access description is location-agnostic, meaning, independent of the repository context. The stored description only includes identities provided by the model. They can then be evaluated to finally obtain the artifact content (or location) in the current environment. 84 | 85 | It is important that this referencing mechanism is not resolved by the OCM tooling. It is the purpose of the deploment tool to resolve this. It is pure convention to follow this pattern. As referencing resources however is a common problem occuring in many scenarios it is recommended to use a common schema. 86 | 87 | ## Absolute Artifact References 88 | 89 | A relative reference can be extended to an location-agnostic absolute reference by extending 90 | the pair by a third value, a component version identity. 91 | 92 |
93 | 94 | ( *<Component Version>* , *<Reference Path> {* , *<Local Artifact Identity> }* ) 95 | 96 |
97 | 98 | A reference can again be transferred into a location-specific reference by adding a repository-context. 99 | 100 | Such a reference can then be used to finally address the content of this artifact by the 101 | following procedure: 102 | 103 | - gain access to the OCM repository described by the repository context. 104 | - gain access to the component version, respectively the component descriptor, by a lookup operation 105 | - follow the resolution procedure for the relative artifact reference. 106 | -------------------------------------------------------------------------------- /doc/05-guidelines/README.md: -------------------------------------------------------------------------------- 1 | # Guidelines (non-normative) 2 | 3 | This chapter contains context information to the OCM core specification. It contains common use-cases where OCM is used and conventions how to make best use of the information in ihe model. 4 | 5 | The specification itself does not rely on the information of this chapter. For interoperability it is strongly recommended to follow the conventions outlined in this chapter. 6 | 7 | * 1 [Transport](01-transport.md#transport) 8 | * 1.1 [Kinds of Transports](01-transport.md#kinds-of-transports) 9 | * 2 [Model Contract](02-contract.md#model-contract) 10 | * 2.1 [Example: Helm deployment](02-contract.md#example-helm-deployment) 11 | * 2.1.1 [Example: Indirect Deployments](02-contract.md#example-indirect-deployments) 12 | * 3 [References](03-references.md#references) 13 | * 3.1 [Relative Artifact References](03-references.md#relative-artifact-references) 14 | * 3.2 [Absolute Artifact References](03-references.md#absolute-artifact-references) 15 | -------------------------------------------------------------------------------- /doc/OCM-Ecosystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/OCM-Ecosystem.png -------------------------------------------------------------------------------- /doc/OCM-Implementation-Model.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-component-model/ocm-spec/7bfbc171e814e73d6e95cfa07cc85813f89a1d44/doc/OCM-Implementation-Model.pptx -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 1 | kind: Component 2 | metadata: 3 | name: ocm-spec 4 | displayName: OCM Specification 5 | description: OCM Specification 6 | tags: 7 | - inner-source 8 | - ocm 9 | - open-source 10 | - open-component-model 11 | spec: 12 | type: 13 | name: specification 14 | lifecycle: production 15 | team: 16 | name: ocm 17 | logo: https://ocm.software/images/logo-image.png 18 | # ci: 19 | # pipelineLinks: 20 | # - name: ci-pipeline 21 | # url: https://sample.com 22 | # icon: .sap-icon--factory 23 | # description: Link to the build job 24 | docs: 25 | techDocsLinks: 26 | - name: OCM Specification 27 | url: https://github.com/open-component-model/ocm-spec/blob/main/README.md 28 | icon: .sa-icon--sys-help-2 29 | description: OCM Specification 30 | issues: 31 | issueTrackerLinks: 32 | - name: Issues 33 | url: https://github.com/open-component-model/ocm-spec/issues 34 | icon: .sa-icon--task 35 | description: Issues created for the component 36 | links: 37 | - name: Getting Started with Flux & OCM 38 | url: https://ocm.software/docs/guides/getting-started-with-ocm-flux/ 39 | icon: .sa-icon--factory 40 | innerSource: 41 | motivation: Open for any SAP contribution 42 | contributions: 43 | - any 44 | skills: 45 | - "Go" 46 | - "SBOM" -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | marko==2.0.0 2 | -------------------------------------------------------------------------------- /scripts/toc_gen.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import sys 3 | 4 | from marko import Markdown # https://marko-py.readthedocs.io/en/latest/ 5 | import marko 6 | import marko.md_renderer 7 | import marko.inline 8 | 9 | def get_module_path() -> Path: 10 | path = Path(__file__) 11 | return path.parent 12 | 13 | class TocGenerator: 14 | def __init__( 15 | self, 16 | prefix: str, 17 | max_level: int, 18 | ): 19 | self.prefix = prefix 20 | self.max_level = max_level 21 | 22 | def header_to_link(header_text: str, prefix: str) -> str: 23 | suffix = header_text.strip().lower().translate(str.maketrans(' ','-', '<>.,;:#"\'*!§$%&/()=?^°\\#')) 24 | if prefix: 25 | return prefix + '#' + suffix 26 | else: 27 | return suffix 28 | 29 | def walk(result: list[marko.block.BlockElement], node: marko.block.BlockElement, prefix: str, max_level: int): 30 | if isinstance(node, marko.block.BlockElement): 31 | if node.children: 32 | for child in node.children: 33 | walk(result, child, prefix, max_level) 34 | 35 | if isinstance(node, marko.block.Heading) and node.level <= max_level: 36 | heading_text = node.children[0].children 37 | ref = header_to_link(heading_text, prefix) 38 | # print(f'add toc: [{heading_text}]({ref}, level: {node.level})') 39 | result.append((node.level, heading_text, ref, prefix)) 40 | 41 | def collect_headings(file_name: Path, prefix: str, max_level: int) -> list[marko.block.BlockElement]: 42 | md = Markdown(renderer=marko.md_renderer.MarkdownRenderer) 43 | with open(file_name) as f: 44 | doc = f.read() 45 | ast = md.parse(doc) 46 | toc_entries = [] 47 | for child in ast.children: 48 | walk(toc_entries, child, prefix, max_level) 49 | return toc_entries 50 | 51 | def generate_toc(out_file_name: str, toc_entries: list[marko.block.BlockElement]): 52 | print(f'Generating toc in {out_file_name}') 53 | with open(out_file_name, 'w') as f: 54 | counters = {} 55 | last_level = -1 56 | current_file = '' 57 | for toc in toc_entries: 58 | level = toc[0] 59 | if level < last_level: 60 | for i in range(level+1, len(counters)+1): 61 | counters[i] = 0 62 | 63 | if counters.get(level): 64 | counters[level] = counters[level] + 1 65 | else: 66 | counters[level] = 1 67 | last_level = level 68 | num_str = ' '*(level-1)*2 + '* ' 69 | for l in range(0, level): 70 | num_str += str(counters[l+1]) + '.' 71 | print(f'{num_str}[{toc[1]}]({toc[2]})', file=f) 72 | 73 | 74 | def get_toc_entries(root_dir: str, working_dir: Path, toc_entries: list[marko.block.BlockElement], max_level: int=3): 75 | all_files = sorted(Path(working_dir).rglob('[0-9][0-9]-*.md')) 76 | for file in all_files: 77 | # print(f' parsing file {file}') 78 | rel_path = file.relative_to(root_dir) 79 | toc = collect_headings(file, prefix=str(rel_path), max_level=max_level) 80 | toc_entries.extend(toc) 81 | 82 | def traverse_spec_markdowns(root_dir: str, out_file_name: str): 83 | print(root_dir) 84 | toc_entries = [] 85 | get_toc_entries(root_dir, root_dir, toc_entries) 86 | generate_toc(out_file_name, toc_entries) 87 | 88 | 89 | def traverse_tree(root_dir: str, out_file_name: str): 90 | print(f'Generating TOC for tree in {root_dir}') 91 | toc_entries = [] 92 | all_dirs = sorted((Path(root_dir) / 'doc').glob('[0-9][0-9]-*')) 93 | all_dirs = [ dir for dir in all_dirs if dir.is_dir() ] # filter directories 94 | toc_entries = [] 95 | for dir in all_dirs: 96 | print(f' processing dir {dir}') 97 | _, chapter_name = dir.name.split('-') 98 | toc_entries.append((1, chapter_name.title(), f'docs/{dir.name}/README.md', None)) 99 | get_toc_entries(root_dir, dir, toc_entries, 2) 100 | print(f' found {len(toc_entries)} entries') 101 | 102 | # Adjust all levels by one because we introduced a new top level 103 | for i, toc in enumerate(toc_entries): 104 | if toc[3]: # keep root level entries, increment all others 105 | toc_entries[i] = (toc[0]+1, toc[1], toc[2], toc[3]) 106 | # print(f'Tupel: {toc_entries[i]}') 107 | 108 | generate_toc(out_file_name, toc_entries) 109 | 110 | 111 | def main(): 112 | out_file_name = 'toc.md' 113 | root_dir = Path('.') 114 | 115 | if Path.exists(root_dir / 'doc'): 116 | # generate global TOC 117 | print('Generating global TOC') 118 | traverse_tree(root_dir, out_file_name) 119 | else: 120 | # generate TOC for all files (01...md, 02...md, ....) 121 | print('Generating chapter TOC') 122 | traverse_spec_markdowns(root_dir, out_file_name) 123 | 124 | 125 | if __name__ == '__main__': 126 | main() 127 | --------------------------------------------------------------------------------