CINXE.COM
Resources REST API (push) - Authentication and Authorization Service
<!doctype html> <html lang="en" class="no-js"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="icon" href="../../assets/images/favicon.png"> <meta name="generator" content="mkdocs-1.3.1, mkdocs-material-8.5.3"> <title>Resources REST API (push) - Authentication and Authorization Service</title> <link rel="stylesheet" href="../../assets/stylesheets/main.7a952b86.min.css"> <link rel="stylesheet" href="../../assets/stylesheets/palette.cbb835fc.min.css"> <link rel="stylesheet" href="../../stylesheets/fonts.css"> <link rel="stylesheet" href="../../stylesheets/kuri-kuri.css"> <script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script> </head> <body dir="ltr" data-md-color-scheme="" data-md-color-primary="none" data-md-color-accent="none"> <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> <label class="md-overlay" for="__drawer"></label> <div data-md-component="skip"> <a href="#rest-services-for-resources-management" class="md-skip"> Skip to content </a> </div> <div data-md-component="announce"> </div> <header class="md-header" data-md-component="header"> <nav class="md-header__inner md-grid" aria-label="Header"> <a href="../.." title="Authentication and Authorization Service" class="md-header__button md-logo" aria-label="Authentication and Authorization Service" data-md-component="logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg> </a> <label class="md-header__button md-icon" for="__drawer"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg> </label> <div class="md-header__title" data-md-component="header-title"> <div class="md-header__ellipsis"> <div class="md-header__topic"> <span class="md-ellipsis"> Authentication and Authorization Service </span> </div> <div class="md-header__topic" data-md-component="header-topic"> <span class="md-ellipsis"> Resources REST API (push) </span> </div> </div> </div> <label class="md-header__button md-icon" for="__search"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> </label> <div class="md-search" data-md-component="search" role="dialog"> <label class="md-search__overlay" for="__search"></label> <div class="md-search__inner" role="search"> <form class="md-search__form" name="search"> <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required> <label class="md-search__icon md-icon" for="__search"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg> </label> <nav class="md-search__options" aria-label="Search"> <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg> </button> </nav> </form> <div class="md-search__output"> <div class="md-search__scrollwrap" data-md-scrollfix> <div class="md-search-result" data-md-component="search-result"> <div class="md-search-result__meta"> Initializing search </div> <ol class="md-search-result__list"></ol> </div> </div> </div> </div> </div> <div class="md-header__source"> <a href="https://gitlab.cern.ch/authzsvc/docs/authzsvc-docs" title="Go to repository" class="md-source" data-md-component="source"> <div class="md-source__icon md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg> </div> <div class="md-source__repository"> authzsvc-docs </div> </a> </div> </nav> </header> <div class="md-container" data-md-component="container"> <main class="md-main" data-md-component="main"> <div class="md-main__inner md-grid"> <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" > <div class="md-sidebar__scrollwrap"> <div class="md-sidebar__inner"> <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0"> <label class="md-nav__title" for="__drawer"> <a href="../.." title="Authentication and Authorization Service" class="md-nav__button md-logo" aria-label="Authentication and Authorization Service" data-md-component="logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg> </a> Authentication and Authorization Service </label> <div class="md-nav__source"> <a href="https://gitlab.cern.ch/authzsvc/docs/authzsvc-docs" title="Go to repository" class="md-source" data-md-component="source"> <div class="md-source__icon md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg> </div> <div class="md-source__repository"> authzsvc-docs </div> </a> </div> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../.." class="md-nav__link"> CERN Authentication and Authorization Services </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2" type="checkbox" id="__nav_2" > <label class="md-nav__link" for="__nav_2"> User authentication <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="User authentication" data-md-level="1"> <label class="md-nav__title" for="__nav_2"> <span class="md-nav__icon md-icon"></span> User authentication </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../user-documentation/authentication-options/" class="md-nav__link"> Authentication options </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/two-factor-authentication/" class="md-nav__link"> Two factor authentication </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/kerberos-authentication/" class="md-nav__link"> Kerberos </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/time-limits/" class="md-nav__link"> Time limits </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/autologon/" class="md-nav__link"> Autologon </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/account-lifecycle/" class="md-nav__link"> Account Lifecycle </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/unconfirmed-identities/" class="md-nav__link"> Unconfirmed identities </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" type="checkbox" id="__nav_3" > <label class="md-nav__link" for="__nav_3"> Securing applications <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Securing applications" data-md-level="1"> <label class="md-nav__title" for="__nav_3"> <span class="md-nav__icon md-icon"></span> Securing applications </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../applications/application-configuration/" class="md-nav__link"> Configuring your application </a> </li> <li class="md-nav__item"> <a href="../../applications/adding-application/" class="md-nav__link"> Adding your application to the service </a> </li> <li class="md-nav__item"> <a href="../../applications/permission-scheme/" class="md-nav__link"> Defining the permissions scheme </a> </li> <li class="md-nav__item"> <a href="../../applications/role-based-permissions/" class="md-nav__link"> Role based permissions (recommended) </a> </li> <li class="md-nav__item"> <a href="../../applications/group-based-permissions/" class="md-nav__link"> Group based permissions </a> </li> <li class="md-nav__item"> <a href="../../applications/sso-registration/" class="md-nav__link"> Registering your application to SSO </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3_7" type="checkbox" id="__nav_3_7" > <label class="md-nav__link" for="__nav_3_7"> SAML <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="SAML" data-md-level="2"> <label class="md-nav__title" for="__nav_3_7"> <span class="md-nav__icon md-icon"></span> SAML </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../user-documentation/saml/saml/" class="md-nav__link"> About </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/saml/config/" class="md-nav__link"> Configuration </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/saml/shibboleth-integration/" class="md-nav__link"> Shibboleth integration </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/saml/shibboleth-migration/" class="md-nav__link"> Shibboleth migration from the old SSO </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3_8" type="checkbox" id="__nav_3_8" > <label class="md-nav__link" for="__nav_3_8"> OIDC <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="OIDC" data-md-level="2"> <label class="md-nav__title" for="__nav_3_8"> <span class="md-nav__icon md-icon"></span> OIDC </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../user-documentation/oidc/oidc/" class="md-nav__link"> About </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/token-requests/" class="md-nav__link"> Token Requests </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/scopes/" class="md-nav__link"> Scopes </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/config/" class="md-nav__link"> OIDC configuration and usage </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/apache/" class="md-nav__link"> Apache configuration </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/securing-apis/" class="md-nav__link"> Securing APIs </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/api-access/" class="md-nav__link"> API Access </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/exchange-for-api/" class="md-nav__link"> Token Exchange </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/device-code/" class="md-nav__link"> Device Code </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/oidc/libraries/" class="md-nav__link"> Suggested libraries </a> </li> </ul> </nav> </li> <li class="md-nav__item"> <a href="../../applications/examples/" class="md-nav__link"> Examples </a> </li> <li class="md-nav__item"> <a href="../../applications/qa-environment/" class="md-nav__link"> QA Environment </a> </li> <li class="md-nav__item"> <a href="../../applications/command-line-tools/" class="md-nav__link"> Command line tools </a> </li> <li class="md-nav__item"> <a href="../../user-documentation/faqs/" class="md-nav__link"> FAQs </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" > <label class="md-nav__link" for="__nav_4"> Group Management System <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Group Management System" data-md-level="1"> <label class="md-nav__title" for="__nav_4"> <span class="md-nav__icon md-icon"></span> Group Management System </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../groups/overview/" class="md-nav__link"> Overview </a> </li> <li class="md-nav__item"> <a href="../../roadmap/group-missing-features/" class="md-nav__link"> Missing features </a> </li> <li class="md-nav__item"> <a href="../../groups/special-groups/" class="md-nav__link"> Special groups </a> </li> <li class="md-nav__item"> <a href="../../groups/dynamic-guidance/" class="md-nav__link"> Dynamic groups </a> </li> <li class="md-nav__item"> <a href="../../groups/csv/" class="md-nav__link"> CSV </a> </li> <li class="md-nav__item"> <a href="../../groups/e-groups-to-gms-sync-scenario/" class="md-nav__link"> E-Groups to GMS transition </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--active md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" type="checkbox" id="__nav_5" checked> <label class="md-nav__link" for="__nav_5"> Resources lifecycle and eligibility <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Resources lifecycle and eligibility" data-md-level="1"> <label class="md-nav__title" for="__nav_5"> <span class="md-nav__icon md-icon"></span> Resources lifecycle and eligibility </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../resources/" class="md-nav__link"> Introduction </a> </li> <li class="md-nav__item"> <a href="../resource-lifecycle-integration/" class="md-nav__link"> Integration </a> </li> <li class="md-nav__item"> <a href="../resource-states/" class="md-nav__link"> Resource States </a> </li> <li class="md-nav__item md-nav__item--active"> <input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc"> <label class="md-nav__link md-nav__link--active" for="__toc"> Resources REST API (push) <span class="md-nav__icon md-icon"></span> </label> <a href="./" class="md-nav__link md-nav__link--active"> Resources REST API (push) </a> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class="md-nav__title" for="__toc"> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> <li class="md-nav__item"> <a href="#creating-a-schema" class="md-nav__link"> Creating a Schema </a> <nav class="md-nav" aria-label="Creating a Schema"> <ul class="md-nav__list"> <li class="md-nav__item"> <a href="#type" class="md-nav__link"> Type </a> </li> <li class="md-nav__item"> <a href="#properties" class="md-nav__link"> Properties </a> </li> <li class="md-nav__item"> <a href="#example" class="md-nav__link"> Example </a> </li> <li class="md-nav__item"> <a href="#the-id-attribute" class="md-nav__link"> The ID attribute </a> </li> <li class="md-nav__item"> <a href="#how-to-validate-your-schema" class="md-nav__link"> How to validate your schema </a> </li> </ul> </nav> </li> <li class="md-nav__item"> <a href="#resource-management-operations" class="md-nav__link"> Resource Management Operations </a> <nav class="md-nav" aria-label="Resource Management Operations"> <ul class="md-nav__list"> <li class="md-nav__item"> <a href="#create-post" class="md-nav__link"> Create (POST) </a> </li> <li class="md-nav__item"> <a href="#update-put" class="md-nav__link"> Update (PUT) </a> </li> <li class="md-nav__item"> <a href="#update-patch" class="md-nav__link"> Update (PATCH) </a> </li> <li class="md-nav__item"> <a href="#delete-delete" class="md-nav__link"> Delete (DELETE) </a> </li> <li class="md-nav__item"> <a href="#read-operations-get" class="md-nav__link"> Read operations (GET) </a> <nav class="md-nav" aria-label="Read operations (GET)"> <ul class="md-nav__list"> <li class="md-nav__item"> <a href="#pagination" class="md-nav__link"> Pagination </a> </li> <li class="md-nav__item"> <a href="#full-import" class="md-nav__link"> Full Import </a> </li> <li class="md-nav__item"> <a href="#delta-import" class="md-nav__link"> Delta Import </a> </li> </ul> </nav> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item"> <a href="../policies/" class="md-nav__link"> Custom Resource Policies </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6" type="checkbox" id="__nav_6" > <label class="md-nav__link" for="__nav_6"> Documents <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Documents" data-md-level="1"> <label class="md-nav__title" for="__nav_6"> <span class="md-nav__icon md-icon"></span> Documents </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../documents/why-keycloak/" class="md-nav__link"> Why Keycloak </a> </li> <li class="md-nav__item"> <a href="../../documents/presentations/" class="md-nav__link"> Presentations </a> </li> <li class="md-nav__item"> <a href="../../documents/our-contributions/" class="md-nav__link"> Our contributions to Keycloak </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7" type="checkbox" id="__nav_7" > <label class="md-nav__link" for="__nav_7"> Services <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Services" data-md-level="1"> <label class="md-nav__title" for="__nav_7"> <span class="md-nav__icon md-icon"></span> Services </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../services/" class="md-nav__link"> Overview </a> </li> <li class="md-nav__item"> <a href="../../services/instances/" class="md-nav__link"> Links to instances </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7_3" type="checkbox" id="__nav_7_3" > <label class="md-nav__link" for="__nav_7_3"> Authorization Service API <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Authorization Service API" data-md-level="2"> <label class="md-nav__title" for="__nav_7_3"> <span class="md-nav__icon md-icon"></span> Authorization Service API </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../authzsvc/overview/" class="md-nav__link"> Overview </a> </li> <li class="md-nav__item"> <a href="../../authzsvc/managed-applications/" class="md-nav__link"> Managing applications for other users </a> </li> <li class="md-nav__item"> <a href="../../authzsvc/roles/" class="md-nav__link"> Role definitions </a> </li> <li class="md-nav__item"> <a href="../../authzsvc/model/" class="md-nav__link"> Model (attributes) </a> </li> <li class="md-nav__item"> <a href="../../authzsvc/examples/" class="md-nav__link"> Examples </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_8" type="checkbox" id="__nav_8" > <label class="md-nav__link" for="__nav_8"> Help <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Help" data-md-level="1"> <label class="md-nav__title" for="__nav_8"> <span class="md-nav__icon md-icon"></span> Help </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../trouble-shooting/edugain-authentication/" class="md-nav__link"> eduGAIN Authentication </a> </li> <li class="md-nav__item"> <a href="../../trouble-shooting/2fa-tips/" class="md-nav__link"> 2FA Tips </a> </li> </ul> </nav> </li> <li class="md-nav__item"> <a href="../../privacy-notice/" class="md-nav__link"> Privacy notice </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_10" type="checkbox" id="__nav_10" > <label class="md-nav__link" for="__nav_10"> Migration notes <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" aria-label="Migration notes" data-md-level="1"> <label class="md-nav__title" for="__nav_10"> <span class="md-nav__icon md-icon"></span> Migration notes </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../migrations/keycloak24/" class="md-nav__link"> Keycloak 24 </a> </li> </ul> </nav> </li> <li class="md-nav__item"> <a href="../../contact/" class="md-nav__link"> Contact </a> </li> </ul> </nav> </div> </div> </div> <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" > <div class="md-sidebar__scrollwrap"> <div class="md-sidebar__inner"> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class="md-nav__title" for="__toc"> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> <li class="md-nav__item"> <a href="#creating-a-schema" class="md-nav__link"> Creating a Schema </a> <nav class="md-nav" aria-label="Creating a Schema"> <ul class="md-nav__list"> <li class="md-nav__item"> <a href="#type" class="md-nav__link"> Type </a> </li> <li class="md-nav__item"> <a href="#properties" class="md-nav__link"> Properties </a> </li> <li class="md-nav__item"> <a href="#example" class="md-nav__link"> Example </a> </li> <li class="md-nav__item"> <a href="#the-id-attribute" class="md-nav__link"> The ID attribute </a> </li> <li class="md-nav__item"> <a href="#how-to-validate-your-schema" class="md-nav__link"> How to validate your schema </a> </li> </ul> </nav> </li> <li class="md-nav__item"> <a href="#resource-management-operations" class="md-nav__link"> Resource Management Operations </a> <nav class="md-nav" aria-label="Resource Management Operations"> <ul class="md-nav__list"> <li class="md-nav__item"> <a href="#create-post" class="md-nav__link"> Create (POST) </a> </li> <li class="md-nav__item"> <a href="#update-put" class="md-nav__link"> Update (PUT) </a> </li> <li class="md-nav__item"> <a href="#update-patch" class="md-nav__link"> Update (PATCH) </a> </li> <li class="md-nav__item"> <a href="#delete-delete" class="md-nav__link"> Delete (DELETE) </a> </li> <li class="md-nav__item"> <a href="#read-operations-get" class="md-nav__link"> Read operations (GET) </a> <nav class="md-nav" aria-label="Read operations (GET)"> <ul class="md-nav__list"> <li class="md-nav__item"> <a href="#pagination" class="md-nav__link"> Pagination </a> </li> <li class="md-nav__item"> <a href="#full-import" class="md-nav__link"> Full Import </a> </li> <li class="md-nav__item"> <a href="#delta-import" class="md-nav__link"> Delta Import </a> </li> </ul> </nav> </li> </ul> </nav> </li> </ul> </nav> </div> </div> </div> <div class="md-content" data-md-component="content"> <article class="md-content__inner md-typeset"> <a href="https://gitlab.cern.ch/authzsvc/docs/authzsvc-docs/-/blob/master/docs/resources/push-rest-api.md" title="Edit this page" class="md-content__button md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25Z"/></svg> </a> <h1 id="rest-services-for-resources-management">REST services for Resources Management</h1> <p>This page describes how to create a REST service so that it can be used by the Authorization Service to provide a lifecycle for a particular type of computing resources.</p> <p>This is required only for the "push" integration mode described in the <a href="../resource-lifecycle-integration/">Resources lifecycle and eligibility integration</a> page.</p> <p>If you are a service manager and you would like to get a lifecycle management for the resources provided by your service (as is currently the case, for example, for computing accounts, Oracle accounts or websites) you can provide a REST interface over your service, that the Authorization Service will call to create, update and delete resources.</p> <p>In particular, you will need to provide:</p> <ul> <li>A way to retrieve the schema of the resources managed by service.</li> <li>Methods for the actual resources management operations (create, read, update, delete).</li> </ul> <h2 id="creating-a-schema">Creating a Schema</h2> <p>The schema defining your computing resource can be added to the Authorization Service by posting to the <code>https://authorization-service-api.web.cern.ch/api/v1.0/{resourceType}</code> <a href="https://authorization-service-api.web.cern.ch/swagger/index.html">API endpoint</a>.</p> <p>The service will issue a <code>GET</code> operation to a certain path (configurable) to retrieve a description of the resources managed by your REST service and related resources you might be interested in.</p> <p>For example, if your system manages objects of type <em>Website</em>, but you also want to have a person as owner of the website, you will have to provide a schema description of the <em>Person</em> type, even if your system will not actually be creating or deleting accounts or identities.</p> <p>Your schema must provide a list of <em>Types</em>, each with a name and a set of properties, as explained below.</p> <h3 id="type">Type</h3> <p><strong>name (string)</strong>: the name of the type, e.g. "person" or "website".</p> <p><strong>properties</strong>: an array of properties.</p> <h3 id="properties">Properties</h3> <p><strong>name (string)</strong>: the name of the property, e.g. "id", "login".</p> <p><strong>property_type (string)</strong>: the type of the property. The possible values are:</p> <ul> <li>string: a string value.</li> <li>number: a numeric value (usually an integer).</li> <li>boolean: true | false.</li> <li>dateTime: a date time, represented with an ISO 8601 formatted string: "2009-02-15T00:00:00Z".</li> <li>reference: the identifier of another object.</li> </ul> <p><strong>array (boolean, optional)</strong>: true if the attribute is an array, false if it’s a single value (default = false).</p> <p><strong>id (boolean, optional)</strong>: true if the attribute is the identifier of the object. Each type must have one and only one attribute with ID = true. This attribute will contain a GUID with the object identifier (default = false).</p> <h3 id="example">Example</h3> <p>This is an example of the json serialization of a schema:</p> <div class="highlight"><pre><span></span><code>[ { "name": "person", "properties": [ { "name": "id", "property_type": "String", "id": true }, { "name": "name", "property_type": "String", } ] }, { "name": "website", "properties": [ { "name": "id", "property_type": "String", "id": true }, { "name": "name", "property_type": "String", }, { "name": "Owner", "property_type": "Reference" }, { "name": "Aliases", "property_type": "String", "array": true } ] } ] </code></pre></div> <h3 id="the-id-attribute">The ID attribute</h3> <p>Each type <em>must</em> define an ID attribute, that will be populated by the Authorization Service <em>with a unique identifier (a GUID)</em>.</p> <p>Your service needs to store this identifier and be able to identify the objects it manages based on that identifier.</p> <h3 id="how-to-validate-your-schema">How to validate your schema</h3> <p><strong>Important:</strong> here is a checklist with the most common problems we have encountered while working with resources schemas:</p> <ul> <li>For the ID property:<ul> <li>Each type in your schema must define a single ID property.</li> <li>All types in your schema must define the same ID property. If type A defines an ID property named X, type B must define a property with name X as the ID property as well.</li> <li>The type of the ID property <strong>must be "String"</strong></li> </ul> </li> <li>For all properties:<ul> <li>The "property_type" must be "String", "Number", "Boolean", "DateTime", "Reference" or "Binary". All other values are invalid.</li> <li>If a property references another object, its type must be "Reference". For example, if a Group has a property called "members", the "property_type" must be simply "Reference", and not "User". The type of the referenced object cannot be enforced in the schema.</li> <li>If several types define a property with the same name, the definition must be identical across types. You cannot define a property with name "X" and property_type "String" in type A and then define a property with name "X" and property_type "Boolean" in type B. The same goes for the "array" value, i.e. the property must always be an array or never.</li> </ul> </li> </ul> <p>There is a <strong>REST types schema validation tool</strong> in the <a href="https://gitlab.cern.ch/authzsvc/synchronization/Cern.Mim.ManagementAgents">Cern.Mim.ManagementAgents project</a> on Gitlab.<br /> Please note that the tool requires PowerShell 7, and can be run with</p> <div class="highlight"><pre><span></span><code>> .\Validate-RestMimSchema.ps1 <schema url or file path> </code></pre></div> <p>The tool performs the checks described above, and if it finds any issue to fix in your schema it will output a warning.</p> <h2 id="resource-management-operations">Resource Management Operations</h2> <p>The Authorization Service will call rest methods on some base address (e.g. <code>https://websites-management.cern.ch/api</code>) followed by the name of the resource as defined in the schema. For example, to get the complete list of websites in the system, it will issue a GET operation at <code>https://websites-management.cern.ch/api/website</code>.</p> <table> <thead> <tr> <th>Operation</th> <th>Verb</th> <th>URL</th> <th>Status codes and return values</th> </tr> </thead> <tbody> <tr> <td>Get all resources of type website</td> <td>GET</td> <td>/website</td> <td>200 + json serialization of envelope with result, resources, pagination and delta data.</td> </tr> <tr> <td>Create a new website</td> <td>POST</td> <td>/website</td> <td>201 (Created) + envelope with json serialization of created object.</td> </tr> <tr> <td>Modify an existing website</td> <td>PUT or PATCH</td> <td>/website/id</td> <td>200 + envelope with json serialization of created object.</td> </tr> <tr> <td>Delete a website</td> <td>DELETE</td> <td>website/id</td> <td>204 (No Content).</td> </tr> </tbody> </table> <p>To <strong>update</strong> an existing resource, the service can either issue a <strong>PUT</strong> or a <strong>PATCH</strong> operation. This can be configured when the REST service is being setup, and cannot be changed later.</p> <p>Return data is always expected to be contained in an <strong>envelope</strong>. This is for uniformity with other system parts and to provide support for pagination and delta operations in <code>GET</code> methods.</p> <p><strong>Write operations (create, update, delete) should be reasonably fast</strong>, because each write operation is blocking for the Authorization Service synchronization mechanism. If an operation (e.g. the creation of a resource) takes a long time, it is better to define a “status” attribute, which should be set to “pending” when the service receives a POST call, and is then updated by the system until it reaches a final “completed” state. This allows the POST call to return immediately; if later the resource ends in a “failed” state, it can simply be deleted, so that the service will re-try to create it at the next round.</p> <h3 id="create-post">Create (POST)</h3> <p>To create an object, the system will issue a <code>POST</code> with the full definition of the object in the body.</p> <p>The expected response is an envelope with the created object in the <code>data</code> field.</p> <p>Example:</p> <p>Method: <code>POST /api/website</code></p> <p>Request body: <div class="highlight"><pre><span></span><code>{ "id" : "fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5", "name" : "some-website", "owner" : "bdc32740-1dcd-4d3a-a491-9fdc364b9e1d", "aliases" : [ "a-site-about-something", "an-amazing-site" ] } </code></pre></div></p> <p>Response body: <div class="highlight"><pre><span></span><code>{ "data" : { "id" : "fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5", "name" : "some-website", "owner" : "bdc32740-1dcd-4d3a-a491-9fdc364b9e1d", "aliases" : [ "a-site-about-something", "an-amazing-site" ] } } </code></pre></div></p> <h3 id="update-put">Update (PUT)</h3> <p>To update an object through a <code>PUT</code> operation, the system will issue a <code>PUT</code> with the full definition of the object in the body.</p> <p>The expected response is an envelope with the full definition of the updated object in the <code>data</code> field.</p> <p>Example:</p> <p>Method: <code>POST /api/website/fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5</code></p> <p>Request body: <div class="highlight"><pre><span></span><code>{ "id" : "fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5", "name" : "the-name-was-changed", "owner" : "bdc32740-1dcd-4d3a-a491-9fdc364b9e1d", "aliases" : [ "a-site-about-something", "an-amazing-site" ] } </code></pre></div></p> <p>Response body: <div class="highlight"><pre><span></span><code>{ "data" : { "id" : "fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5", "name" : "the-name-was-changed", "owner" : "bdc32740-1dcd-4d3a-a491-9fdc364b9e1d", "aliases" : [ "a-site-about-something", "an-amazing-site" ] } } </code></pre></div></p> <h3 id="update-patch">Update (PATCH)</h3> <p>To update an object through a <code>PATCH</code> operation, the system will issue a <code>PATCH</code> with the object's changed attributes in the body.</p> <p>The expected response is an envelope with the full definition of the updated object in the <code>data</code> field.</p> <p>Example:</p> <p>Method: <code>PATCH /api/website/fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5</code></p> <p>Request body: <div class="highlight"><pre><span></span><code>{ { "op": "replace", "path": "/name", "value": "the-name-was-changed" } } </code></pre></div></p> <p>Response body: <div class="highlight"><pre><span></span><code>{ "data" : { "id" : "fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5", "name" : "the-name-was-changed", "owner" : "bdc32740-1dcd-4d3a-a491-9fdc364b9e1d", "aliases" : [ "a-site-about-something", "an-amazing-site" ] } } </code></pre></div></p> <h3 id="delete-delete">Delete (DELETE)</h3> <p>To delete an object, the system will issue a <code>DELETE</code> with no body.</p> <p>Example:</p> <p>Method: <code>DELETE /api/website/fa58fb40-e2c2-42db-8e76-a6aa6b1bfab5</code></p> <h3 id="read-operations-get">Read operations (GET)</h3> <p>After the Authorization Service has created, updated and deleted the resouces it needed to, it reads back data from the REST service, to determine if the objects are actually in the state they are expected to be.</p> <p>This can be done with <strong>full import</strong> operations, where the service asks the REST API “give me all the resources as they are now”, or with <strong>delta import</strong> operations, where the REST API asks the external system “give me all the changes since a certain situation”.</p> <p>Reading is the most critical operation in terms of performance for the synchronization process, and therefore it's also the one that requires more work to be supported.</p> <p>The two key features that you will need to implement are <strong>pagination</strong> and support for <strong>delta operations</strong>.</p> <h4 id="pagination">Pagination</h4> <p>The data is always expected to be contained in an envelope, which must have this format:</p> <div class="highlight"><pre><span></span><code>{ // Pagination information "pagination": { // Relative URL to invoke to continue the enumeration. REQUIRED. // The Authorization Service will keep calling GET with the 'next' URL until this field is empty. "next": "/api/person?limit=5&lastId=id005&nextDelta=eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==", // Total number of objects. Optional, useful for troubleshooting. "total": 15, // Maximum number of objects returned. Optional, useful for troubleshooting. "limit": 5 }, "delta": { // Information that your service will need to receive to provide a delta import from the current situation. // If your service supports delta operations, this field is REQUIRED. "token": "eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==" }, // An array with the actual objects "data": [ { "id": "id001", "name": "Amelia Gabriela" }, // more objects ... { "id": "id005", "name": "Clotilda Karin" } ] } </code></pre></div> <p>The REST API must return in the <code>pagination:next</code> field the relative URL to call to continue the enumeration.</p> <h4 id="full-import">Full Import</h4> <p>To retrieve the complete list of persons, the MA will start with this call:</p> <p><code>GET /api/person?limit=1000</code></p> <p>The REST API will return:</p> <div class="highlight"><pre><span></span><code>{ "data": [ /* objects here... */ ], "pagination": { "next": "/api/person?limit=1000&lastId=id005&nextDelta=eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==" }, "delta": { "token": "eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==" } } </code></pre></div> <p>Since the <code>pagination:next</code> field is not empty, the Authorization Service will call:</p> <p><code>GET /api/person?limit=5&lastId=id005&nextDelta=eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==</code></p> <p>Note that the REST API is passing back to itself the value of the delta token, so that continuing the operation can be completely stateless for the REST service.</p> <p>If the REST API returns:</p> <div class="highlight"><pre><span></span><code>{ "data": [ /* more objects here... */ ], "pagination": { "next": null }, "delta": { "token": "eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==" } } </code></pre></div> <p>Since the <code>pagination:next</code> field is empty, the Authorization Service will consider that the import operation is completed.</p> <h4 id="delta-import">Delta Import</h4> <p>Delta import operations are used by MIM to ask to the REST service what has changed since the last import operation.</p> <p>If the last import operation was the full import of the previous example, the first delta import call will be</p> <p><code>GET /api/person?limit=1000&delta=eyJQZXJzb25zRGVsdGEiOjE1LCJXZWJzaXRlc0RlbHRhIjowfQ==</code></p> <p>The presence of the <code>delta</code> parameter indicates to the REST service that this is a delta operation. Therefore, the service must return to MIM all the changes since the moment indicated by the value of the delta parameter in the query string.</p> <p>Let’s suppose that since the moment indicated by the delta value, there have been 3 changes in the connected system:</p> <p>The person with ID id1001 was created. The person with ID id1002 was modified. The person with ID id1003 was deleted.</p> <p>The REST API must return something like this:</p> <div class="highlight"><pre><span></span><code>{ "data": [ // note that now we have operation type and object definition { "operation": "add", "object": { "ID": "id1001", "Name": "Keyser Söze" } }, { "operation": "modify", "object": { "ID": "id1002", "Name": "Roger Verbal Kint" } }, { "operation": "delete", "object": { "ID": "id1003" // only ID is relevant in case of delete } } ], "pagination": { "total": 3, "limit": 1000, "token": null }, "delta": { // a new token that represents the data to pass back at the next delta // operation "token": "QWxsIHdvcmsgYW5kIG5vIHBsYXkgbWFrZXMgSmFjayBhIGR1bGwgYm95Lg==" } } </code></pre></div> <p>Note that now the <code>data</code> array does not simply contain objects, but <strong>the operation type and the object definition</strong>. In case of added or modified object, the REST service must return the definition of the whole object in its current state, while for deleted objects only the ID is relevant.</p> </article> </div> </div> </main> <footer class="md-footer"> <nav class="md-footer__inner md-grid" aria-label="Footer" > <a href="../resource-states/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Resource States" rel="prev"> <div class="md-footer__button md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg> </div> <div class="md-footer__title"> <div class="md-ellipsis"> <span class="md-footer__direction"> Previous </span> Resource States </div> </div> </a> <a href="../policies/" class="md-footer__link md-footer__link--next" aria-label="Next: Custom Resource Policies" rel="next"> <div class="md-footer__title"> <div class="md-ellipsis"> <span class="md-footer__direction"> Next </span> Custom Resource Policies </div> </div> <div class="md-footer__button md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class="md-copyright"> Made with <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"> Material for MkDocs </a> </div> </div> </div> </footer> </div> <div class="md-dialog" data-md-component="dialog"> <div class="md-dialog__inner md-typeset"></div> </div> <script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.5bf1dace.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script> <script src="../../assets/javascripts/bundle.37e9125f.min.js"></script> </body> </html>