|
2 | 2 |
|
3 | 3 | [](https://github.com/metal-stack/api/actions/workflows/main.yml) [](https://pkg.go.dev/github.com/metal-stack/api)   [](https://goreportcard.com/report/github.com/metal-stack/api) |
4 | 4 |
|
5 | | -This is the POC V2 API of [metal-stack.io](https://metal-stack.io) to implement MEP-4. |
| 5 | +> [!IMPORTANT] |
| 6 | +> Please note that this repository is still in alpha stage. For now, the primary API is still defined in the [metal-api](https://github.com/metal-stack/metal-api) project. We will make a special announcement when this repository becomes GA. |
6 | 7 |
|
| 8 | +This is the V2 API of [metal-stack.io](https://metal-stack.io) to implement [MEP-4](https://metal-stack.io/docs/MEP-4-multi-tenancy-for-the-metal-api). |
7 | 9 |
|
8 | | -TODO: |
| 10 | +## Usage examples |
9 | 11 |
|
10 | | -- validate all fields in all messages, also review them |
11 | | -- get rid of exposed nsq, replace with grpc streaming |
12 | | -- try to implement a generic reconcile which spans multiple backends |
| 12 | +Can be found in the [examples](examples/) folder. |
13 | 13 |
|
14 | | -Meeting Minutes: |
| 14 | +## Conventions |
15 | 15 |
|
16 | | -- We stick with networks without a project and treat them as global resource |
17 | | -- Write down a table with use cases which are actually possible and check if the new implementation still allows them |
18 | | -- If project is "" its a global resource, otherwise its project scoped. This requires more checks regarding visibility. |
19 | | - |
20 | | -List of possible use cases: |
21 | | - |
22 | | -- Admin creates a underlay network for a partition |
23 | | - - creation of firewall and switch underlay ip allocation, currently only the firewall ip is allocated |
24 | | - the switch VNI and Loopback ips are actually manually allocated by the ansible deployment |
25 | | -- Admin creates a super network for a partition (should be possible without partition for zonal support) |
26 | | - - only project scoped child network allocation is possible, no ip address allocation |
27 | | - - In Addition to defaultchildprefixlength a min childprefixlength per AF should be possible |
28 | | -- Admin creates a external network, either internet or other campus networks where communication must be possible |
29 | | - - Only project scoped ip address allocation is possible, no child networks |
30 | | -- Admin creates a external super network which is used for project scoped child networks and inherit vrfShared |
31 | | - - Users can allocate child which are then project scoped with their own project. |
32 | | -- Admin creates a shared network which is project scoped in a partition which can be used for storage for example. |
33 | | - - Users can allocate a IP address in this network which are scoped with their project. |
34 | | - |
35 | | -- User allocates a child network from a super network to be used as node network, this is scoped to his project |
36 | | -- User allocates ip addresses from his child networks, which are then scoped with the same project as the network itself. |
37 | | -- User allocates ip addresses from global networks, which are then project scoped with his project |
38 | | -- User allocates ip addresses from shared networks, which are then project scoped with his project |
39 | | - |
40 | | -Future Use Cases: |
41 | | - |
42 | | -tenant-super-namespaced-network 10.0.0.0/16 "" |
43 | | -├─╴ 10.0.0.0/16 project-a |
44 | | - ├──╴10.0.0.0/24 project-a |
45 | | - ├──╴10.0.1.0/24 project-a |
46 | | -├─╴ 10.0.0.0/16 project-b |
47 | | - ├──╴10.0.0.0/24 project-b |
48 | | - ├──╴10.0.1.0/24 project-b |
49 | | - |
50 | | -- Admin can create super networks for project namespaced child networks. These networks will always start at the same prefix as the parent: |
51 | | - Example: |
52 | | - Parent: 10.0.0.0/16 |
53 | | - Child 1 in project 1 : 10.0.0.0/24 |
54 | | - Child 2 in project 1 : 10.0.1.0/24 |
55 | | - Child 3 in project 1 : 10.0.2.0/24 |
56 | | - Child 4 in project 1 : 10.0.3.0/24 |
57 | | - Child 5 in project 1 : 10.0.4.0/24 |
58 | | - |
59 | | - Child 1 in project 2 : 10.0.0.0/24 |
60 | | - Child 2 in project 2 : 10.0.1.0/24 |
61 | | - Child 3 in project 2 : 10.0.2.0/24 |
62 | | - Child 4 in project 2 : 10.0.3.0/24 |
63 | | - Child 5 in project 2 : 10.0.4.0/24 |
64 | | - |
65 | | -# Meeting Minutes 2nd Call |
66 | | - |
67 | | -- Check if is possible to create a Internet access network for single customer usage with specified destination prefixes |
| 16 | +Method options provide an intuitve and declarative way of providing annotations to service methods. |
| 17 | +These are used for scoping api-methods, which are getting utilized for authentication, authorization and auditing (mainly in interceptors). |
68 | 18 |
|
| 19 | +### Motivational Example |
69 | 20 |
|
70 | 21 | ```proto |
71 | | -enum NetworkType { |
72 | | - // NETWORK_TYPE_UNSPECIFIED indicates a unknown network type |
73 | | - NETWORK_TYPE_UNSPECIFIED = 0; |
74 | | - // NETWORK_TYPE_EXTERNAL indicates network where multiple projects can allocate ips, it offers connectivity to external networks |
75 | | - // In most cases this is the internet network or a network which offers connectivity to legacy datacenter networks. |
76 | | - // If it is not project scoped everyone can allocate Ips in this network, otherwise only from the same project ip allocation is possible. |
77 | | - NETWORK_TYPE_EXTERNAL = 1 [(enum_string_value) = "external"]; |
78 | | - // NETWORK_TYPE_UNDERLAY indicates a underlay network |
79 | | - // The underlay network connects all switches and the firewalls to build a EVPN dataplane |
80 | | - // It is not project scoped. Is part of the dataplane and reserved for administrative purposes. |
81 | | - NETWORK_TYPE_UNDERLAY = 2 [(enum_string_value) = "underlay"]; |
82 | | -
|
83 | | - // NETWORK_TYPE_SUPER indicates a super network which is only used to create child networks |
84 | | - // If the vrf id is given, child networks will inherit this vrf. |
85 | | - // If the vrf id is nil in this network, child vrf is taken from the pool. |
86 | | - // If the partition is given, child networks inherit the partition. |
87 | | - // If the partition is nil, child networks also do not have a partition (i.e. requires vrf is distributed across all partitions). |
88 | | - // For child creation destination prefixes will be inherited |
89 | | - // If this is project scoped, child project must match, otherwise can be freely specified. |
90 | | - NETWORK_TYPE_SUPER = 3 [(enum_string_value) = "super"]; |
91 | | - // NETWORK_TYPE_SUPER_NAMESPACED indicates a super network which is only used to create child networks. |
92 | | - // All rules from NETWORK_TYPE_SUPER apply for them as well. |
93 | | - // In addition, a network namespace will be created for every project. Child networks per project will have disjunct prefixes. |
94 | | - // Prefix allocation will start again with the same base cidr for every project / namespace. |
95 | | - // This will allow the creation of much more child networks from a given super network size. |
96 | | - NETWORK_TYPE_SUPER_NAMESPACED = 4 [(enum_string_value) = "super-namespaced"]; |
97 | | -
|
98 | | - // NETWORK_TYPE_CHILD indicates a child network of a project. |
99 | | - // This is the only network type that can be created by a user. |
100 | | - // Connectivity to external networks is not possible without going through an additional firewall in this network which creates connectivity to other networks. |
101 | | - // Such a network will be created either from a super, or super namespaced. |
102 | | - NETWORK_TYPE_CHILD = 5 [(enum_string_value) = "child"]; |
103 | | - // NETWORK_TYPE_CHILD_SHARED indicates a child network of a project which allows the allocation of ips from different projects. |
104 | | - // Connectivity to external networks is not possible, as for normal child networks. |
105 | | - // These networks are usually used to provide connectivity to shared services which are created in child networks, e.g. storage. |
106 | | - // With this approach the number of hops can be reduced to the bare minimum in order to increase availability and performance. |
107 | | - NETWORK_TYPE_CHILD_SHARED = 6 [(enum_string_value) = "child-shared"]; |
| 22 | +service IPService { |
| 23 | + // Get an ip |
| 24 | + rpc Get(IPServiceGetRequest) returns (IPServiceGetResponse) { |
| 25 | + option (project_roles) = PROJECT_ROLE_OWNER; |
| 26 | + option (project_roles) = PROJECT_ROLE_EDITOR; |
| 27 | + option (project_roles) = PROJECT_ROLE_VIEWER; |
| 28 | + option (auditing) = AUDITING_EXCLUDED; |
| 29 | + } |
| 30 | + // Create an ip |
| 31 | + rpc Create(IPServiceCreateRequest) returns (IPServiceCreateResponse) { |
| 32 | + option (project_roles) = PROJECT_ROLE_OWNER; |
| 33 | + option (project_roles) = PROJECT_ROLE_EDITOR; |
| 34 | + } |
| 35 | +} |
| 36 | +
|
| 37 | +// IPServiceCreateRequest is the request payload for a ip create request |
| 38 | +message IPServiceCreateRequest { |
| 39 | + // Network from which the IP should be created |
| 40 | + string network = 1 [(buf.validate.field).string = { |
| 41 | + min_len: 2 |
| 42 | + max_len: 128 |
| 43 | + }]; |
| 44 | + // Project of the ip |
| 45 | + string project = 2 [(buf.validate.field).string.uuid = true]; |
| 46 | + // Name of the ip |
| 47 | + optional string name = 3 [(buf.validate.field).string.(metalstack.api.v2.is_name) = true]; |
| 48 | + // Description of the ip |
| 49 | + optional string description = 4 [(buf.validate.field).string.(metalstack.api.v2.is_description) = true]; |
| 50 | + // IP if given try to create this ip if still available |
| 51 | + optional string ip = 5 [(buf.validate.field).string.ip = true]; |
| 52 | + // Machine for which this ip should get created |
| 53 | + optional string machine = 6 [(buf.validate.field).string.uuid = true]; |
| 54 | + // Labels to put onto the ip |
| 55 | + optional Labels labels = 7; |
| 56 | + // Type of the IP, ether ephemeral (default), or static |
| 57 | + optional IPType type = 8 [(buf.validate.field).enum.defined_only = true]; |
| 58 | + // Addressfamily of the IP to create, defaults to ipv4 |
| 59 | + optional IPAddressFamily address_family = 9 [(buf.validate.field).enum.defined_only = true]; |
108 | 60 | } |
109 | 61 | ``` |
110 | 62 |
|
111 | | -Please validate these enums with the given use-cases above. |
| 63 | +In this example we can see the motivation behind the method options. |
| 64 | + |
| 65 | +1. Get: can be issued by project owner, editor, viewer and is excluded from auditing |
| 66 | +2. Allocate: can be used by project owner, editor |
| 67 | +3. Both methods are project-scoped, since they are annotated by a project role -> Request object needs to have the **project** field in order to specify the target project of the service method |
| 68 | + |
| 69 | +Further explanations are explained in the following. |
| 70 | + |
| 71 | +### Auth |
| 72 | + |
| 73 | +These options specify the RBAC of the api-endpoint. |
| 74 | + |
| 75 | +| Option | Description | Values | Explanation | |
| 76 | +| -------------- | -------------------------------------------- | ----------- | ------------------------------------------------------ | |
| 77 | +| TENANT_ROLE\_ | Specifies the required tenant role | UNSPECIFIED | | |
| 78 | +| | | OWNER | tenant owner | |
| 79 | +| | | EDITOR | tenant editor | |
| 80 | +| | | VIEWER | tenant viewer | |
| 81 | +| | | GUEST | tenant guest | |
| 82 | +| PROJECT_ROLE\_ | Specifies the required project role | UNSPECIFIED | | |
| 83 | +| | | OWNER | project owner | |
| 84 | +| | | EDITOR | project editor | |
| 85 | +| | | VIEWER | project viewer | |
| 86 | +| ADMIN_ROLE\_ | Specifies the required admin role | UNSPECIFIED | | |
| 87 | +| | | EDITOR | admin editor | |
| 88 | +| | | VIEWER | admin viewer | |
| 89 | +| VISIBILITY\_ | Specifies the visibility of the api-endpoint | UNSPECIFIED | | |
| 90 | +| | | PUBLIC | api-method is visible to public, a token is not needed | |
| 91 | +| | | SELF | api-method is scoped to owner resources | |
| 92 | + |
| 93 | +> [!IMPORTANT] |
| 94 | +> |
| 95 | +> Every operation needs at least an option, which references the scope of the request: **ROLE** or **VISIBILITY** |
| 96 | +
|
| 97 | +> [!CAUTION] |
| 98 | +> |
| 99 | +> If we use a Tenant or Project role, the request will be respectively scoped as Tenant or Project request. |
| 100 | +> Tenant-Requests must have the field **login**, which is the tenant id and specifies the tenant on which the service-method is scoped. |
| 101 | +> Project-Requests must have the field **project**, which is the project id and specifies the project on which the service-method is scoped. |
| 102 | +
|
| 103 | +### Auditing |
| 104 | + |
| 105 | +For traceability we require to store audit-logs. |
| 106 | + |
| 107 | +| Option | Description | Values | Explanation | |
| 108 | +| ---------- | ---------------------------------------- | ----------- | ------------------------ | |
| 109 | +| AUDITING\_ | Specifies if the api-endpoint is audited | UNSPECIFIED | DEFAULT: included | |
| 110 | +| | | INCLUDED | operation is audited | |
| 111 | +| | | EXCLUDED | operation is not audited | |
0 commit comments