{"id":28194262,"url":"https://github.com/monkey-projects/oci-sign","last_synced_at":"2025-05-16T13:12:02.995Z","repository":{"id":176963163,"uuid":"659789575","full_name":"monkey-projects/oci-sign","owner":"monkey-projects","description":"Generates signature headers to send requests to Oracle Cloud Infrastructure (OCI).","archived":false,"fork":false,"pushed_at":"2025-03-25T07:38:06.000Z","size":83,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-25T16:23:48.260Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monkey-projects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-06-28T15:03:35.000Z","updated_at":"2025-03-25T07:38:09.000Z","dependencies_parsed_at":"2024-01-12T13:53:33.515Z","dependency_job_id":null,"html_url":"https://github.com/monkey-projects/oci-sign","commit_stats":null,"previous_names":["monkey-projects/oci-sign"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monkey-projects%2Foci-sign","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monkey-projects%2Foci-sign/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monkey-projects%2Foci-sign/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monkey-projects%2Foci-sign/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monkey-projects","download_url":"https://codeload.github.com/monkey-projects/oci-sign/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535799,"owners_count":22087399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-16T13:11:45.501Z","updated_at":"2025-05-16T13:12:02.989Z","avatar_url":"https://github.com/monkey-projects.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Monkey Projects OCI Signature Generator\n\nGenerates signatures for an HTTP request for [OCI](https://cloud.oracle.com).\n\n## Why?\n\nWhy not use the provided Oracle SDK for Java?  Because I want a library\nthat is small and has as few dependencies as possible, so I can use it\nin GraalVM projects.  More specifically, to use them in native images\nfor OCI [functions](https://fnproject.io).\n\n## Design\n\nI have written the code according to the [specs provided by Oracle](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm#six).\nThese were however incomplete, so I also had to reverse engineer their Java\ncode somewhat.  But eventually that did the trick.\n\n## How to use it?\n\n[![Clojars Project](https://img.shields.io/clojars/v/com.monkeyprojects/oci-sign.svg)](https://clojars.org/com.monkeyprojects/oci-sign)\n\nInclude the library in your project:\n```clojure\n{:deps {com.monkeyprojects/oci-sign {:mvn/version ..latest..}}}\n```\n\nThen require the namespace, and invoke the `sign-headers` and `sign` functions.\nThe `sign-headers` takes a regular Ring request, and extracts the headers that\nshould be included in the signature.  Which headers depends on the kind of request.\nIt always includes the date, host and a generated value that combines the method\nand the path.  For `PUT` and `POST`, it also includes a body hash, but there\nare exceptions (see below).  You can also influence this by passing an additional\nboolean `exclude-body?`, to forcibly exclude the body from the signature, even\nif it is a `POST` or `PUT`.\n\nThe `sign-headers` returns a map that can then be passed to `sign`, which will\ngenerate the actual signature using the configuration.  The configuration holds\na private key, but also values that are used to build a `keyId` header value.\nThese headers should then be included in your request to the OCI endpoint.\n\n```clojure\n(require '[monkey.oci.sign :as sign])\n\n;; Configuration should be according to spec\n(def config {:tenancy-ocid \"...\"\n             :user-ocid \"...\"\n\t     :key-fingerprint \"...\"\n\t     :private-key some-pk})\n(def req {:url \"https://some-oci-url\"\n          :method :get})\n;; Generate the signature headers\n(def headers (sign/sign config (sign/sign-headers req)))\n\n;; Send the request, e.g. using http-kit\n(require '[org.httpkit.client :as http])\n(http/get (:url req) {:headers headers})\n;; Process the result...\n```\n\nThe configuration should contain the `:tenancy-ocid`, `:user-ocid`, `:key-fingerprint`\nand the `:private-key`.  The private key must be an `RSAPrivateKey` object.  You can\nget it by reading it from a file and then parse it using [the buddy library](https://cljdoc.org/d/buddy/buddy-core/1.11.418/api/buddy.core.keys.pem).\n\nThe request must at least contain the `:url` and `:method` (as a keyword).  You can also\nadd the date but it's best to let the signer generate and format it.\n\n## Martian\n\nIf you're using [Martian](https://github.com/oliyh/martian), you can include an interceptor\nthat is provided by this library to sign requests.  It takes the same configuration map\nas the basic signing functions, with an extra option (`exclude-body?`, more on that below):\n\n```clojure\n(require '[monkey.oci.sign.martian :as mm])\n\n;; Create Martian context that includes the signer interceptor\n(def ctx (martian/bootstrap\n          \"http://api-host\"\n\t  routes\n\t  {:interceptors (concat martian/default-interceptors\n\t                         [(mm/signer conf)\n\t\t\t\t  martian-http/perform-request])}))\n;; Now send a request\n(martian/response-for ctx :my-request {:key \"value\"})\n;; The request will include authorization headers for OCI.\n```\n\n### Excluding The Body\n\nNormally, for `PUT`, `POST` and `PATCH` requests, the body will also be included in the\nsignature calculation.  However, [some requests](https://docs.oracle.com/en-us/iaas/api/#/en/objectstorage/20160918/Object/PutObject)\nrequire special treatment.  To allow for this, the signer accepts an additional\nconfiguration property, `exclude-body?` which is a function that takes the request context\nas argument and returns `true` if the body should be explicitly excluded, even though\nit's a request with a body and one of the aforementioned HTTP methods.\n\n## Copyright\n\nCopyright (c) 2023 by Monkey Projects BV.\nLicensed under [MIT](LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonkey-projects%2Foci-sign","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonkey-projects%2Foci-sign","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonkey-projects%2Foci-sign/lists"}