Where can i find the digest for my docker image so I can delete it from the Registry? - docker-registry

Update
After reading the documentation a few more times, I realized I'b been looking in the wrong place for the digest. It is NOT in the manifest.
If you do a HEAD or GET on the v2/name/manifests/tag you will get a header (Docker-Content-Digest) which contains the digest:
Server nginx
Date Sat, 02 Nov 2019 19:01:16 GMT
Content-Type application/vnd.docker.distribution.manifest.v1+prettyjws
Content-Length 2839
Connection keep-alive
Docker-Content-Digest sha256:fcb864bea187b2efbf23d1032052461170fcb482e2dd99f9db5f9a8b538e553d
Docker-Distribution-Api-Version registry/2.0
Depending on the version of your Registry (or may be unrelated to that), the inclusion of a specific header at the time of sending GET or HEAD will cause a different digest to be returned.
This header is:
Accept: application/vnd.docker.distribution.manifest.v2+json
Even though the version of Registry that I'm dealing with is 2.0 inclusion of this header causes a different value to be returned for Docker-Content-Digest
Anyways, I tried both variations and I'm still not able to delete each time getting
{
"errors": [
{
"code": "DIGEST_INVALID",
"message": "provided digest did not match uploaded content"
}
]
}
Here's a link to the documenation in case someone's interested in it:
https://docs.docker.com/registry/spec/api/
Original
I have the following manifest which is downloaded for my image. I have tried every string here in place of the Digest but I have not been able to do that.
Could someone point out which one of these is the digest that i need for a Delete command?
I am using a DELETE http request with the following formulation:
https://my_registry.com/v2/demo/derivedimage/manifests/<whatever the digest is supposed to be here>
This is the error I get every time:
{
"errors": [
{
"code": "DIGEST_INVALID",
"message": "provided digest did not match uploaded content"
}
]
}
{
"schemaVersion": 1,
"name": "demo/derivedimage",
"tag": "4c3a6f78fe709a098a0d24a2c43639e7e170bc5981004554a154245662fea132",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
},
{
"blobSum": "sha256:0f8c40e1270f10d085dda8ce12b7c5b17cd808f055df5a7222f54837ca0feae0"
}
],
"history": [
{
"v1Compatibility": "{\"architecture\":\"amd64\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"sh\"],\"ArgsEscaped\":true,\"Image\":\"sha256:02cc0eb9e9d093c512e57d613a9c1d89b0b50b551bbed33e3116459e7d15ee7e\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"container\":\"e24c19c10096d9b60b9ac2276cc24ec9a1ab93e8330dff511362b8e983a4e040\",\"container_config\":{\"Hostname\":\"e24c19c10096\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) \",\"CMD [\\\"sh\\\"]\"],\"ArgsEscaped\":true,\"Image\":\"sha256:02cc0eb9e9d093c512e57d613a9c1d89b0b50b551bbed33e3116459e7d15ee7e\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"created\":\"2019-10-30T23:20:37.206592274Z\",\"docker_version\":\"18.06.1-ce\",\"id\":\"d624e6ec746cd764114cfd7f4ab1fb0852e670c10df15adb1e75b4f99e4123be\",\"os\":\"linux\",\"parent\":\"9f31ac69fd90b9035252a2e1bac45e3d43b7d32316be7e4ac7a737d9d11b092b\",\"throwaway\":true}"
},
{
"v1Compatibility": "{\"id\":\"9f31ac69fd90b9035252a2e1bac45e3d43b7d32316be7e4ac7a737d9d11b092b\",\"created\":\"2019-10-30T23:20:37.083008444Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:1141b81e5149cc37c4346ee17e282cca8c7016a9bcfeb7a54842a87ecf8419d4 in / \"]}}"
}
],
"signatures": [
{
"header": {
"jwk": {
"crv": "P-256",
"kid": "3NQM:K5YD:M3XF:EKJD:4S64:3772:BJOT:JIMR:NX4R:2XYS:IDNA:NOKL",
"kty": "EC",
"x": "k6pZfyr-dKYLri5KJCL70UmNLCQnfUh2lAC_nDK9PVw",
"y": "MhrKOUbx1sgsbF0kG9d5bfvkVaxaFWiKlWTwgFyHkbQ"
},
"alg": "ES256"
},
"signature": "0TWLKZlltDA4kQJR4orhg7NenglG2OevQMSaN-RXCwFod7cyO5VFLVEeBDvsFhuAsvsw8mO475g1G9bW_Zh-aA",
"protected": "eyJmb3JtYXRMZW5ndGgiOjIxOTIsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxOS0xMS0wMVQwNDowMTowNloifQ"
}
]
}

The answer is how the digest is sent. In my case, I had to include the header:
Accept: application/vnd.docker.distribution.manifest.v2+json
to get the right digest in the incoming header Docker-Content-Digest
Second I had to include the "sha256:" in the outgoing digest. Example:
curl -vk -X DELETE https://my_registry.com/v2/demo/derivedimage/manifests/sha256:679b1c1058c1f2dc59a3ee70eed986a88811c0205c8ceea57cec5f22d2c3fbb1
And the reponse is:
HTTP/1.1 202 Accepted

Related

Why is the Azure Devops API telling me that I must have these parameters for my Push request when I already do?

I'm trying to make a Git push request to our Azure Devops server via the API. The address is https://MYSITE.visualstudio.com/MYPROJECT/_apis/git/repositories/2b34d4f7-2c1f-42e7-8861-u0ba34f72b40/pushes?api-version=5.1 and the body is as follows:
{
"commits": [
{
"comment": "Just a dummy commit",
"changes": [
{
"changeType": "edit",
"item": {
"path": "/src/MYPROJECT/MYPROJECT.csproj"
},
"newContent": {
"content": "beans",
"contentType": "rawText"
}
}
]
}
],
"refUpdates": [
{
"name": "refs/heads/TestDummyPRs/upgradeProjectToLatest",
"oldObjectId": "058da4f3328cb1048cb43faf3b5158bc3b025615"
}
]
}
I'm getting the following error:
Web Request Failed after 4 attempts. Request: https://MYSITE.visualstudio.com/MYPROJECT/_apis/git/repositories/2b34d4f7-2c1f-42e7-8861-u0ba34f72b40/pushes?api-version=5.1. Status: BadRequest. Response: Invalid status code [BadRequest]. Response: {"$id":"1","innerException":null,"message":"The parameters are incorrect. A posted push must contain exactly one commit and one refUpdate.\r\nParameter name: newPush","typeName":"Microsoft.TeamFoundation.SourceControl.WebServer.InvalidArgumentValueException, Microsoft.TeamFoundation.SourceControl.WebServer","typeKey":"InvalidArgumentValueException","errorCode":0,"eventId":0}
"A posted push must contain exactly one commit and one refUpdate" doesn't seem entirely reasonable as that's exactly what I have in my body. Does anybody know what might be going on here?
Note that I am having no issues making other web requests, such as creating branches or retrieving file contents.
I expected my web request to proceed smoothly, and to create a Push containing the specified commit to the specified refUpdate.
I have made a manual push for via the Azure Devops web interface and caught the network traffic, and I grabbed the following JSON request out of it:
{
"commits": [
{
"changes": [
{
"changeType": 2,
"item": {
"path": "/src/MYPROJECT/MYPROJECT.csproj"
},
"newContent": {
"content": "beans",
"contentType": 0
}
}
],
"comment": "Just a dummy commit"
}
],
"refUpdates": [
{
"name": ""refs/heads/TestDummyPRs/upgradeProjectToLatest",
"oldObjectId": "058da4f3328cb1048cb43faf3b5158bc3b025615"
}
]
}
This seems to be meaningfully identical to the Push I'm making from my code, other than the enum fields using numerical values instead of text. I have tried my code with numerical values for enums, but that didn't change anything about the error.
I found the issue. The web request from my application was being sent with UTF-16 encoding, whereas Postman had defaulted to UTF-8 encoding. I changed my application to use UTF-8 and it worked.

Apple app site association - bad JSON content

The Apple-app-site association is failing. Haven't found a solution yet. I checked for valid JSON in the JSON validator which says -valid JSON
But it doesn't redirect to the app. I have hosted
The apple-app-site association file (without the extension as mentioned in the Apple documentation) has no restrictions on the web server and that URL. I have validated the link on this web page [https://branch.io/resources/aasa-validator]
But it didn't redirect the app.
I found this method to validate AASA files
curl -v https://app-site-association.cdn-apple.com/a/v1/yourdomain.com
The response is like this
Mark bundle as not supporting multiuse
HTTP/1.1 404 Not Found
Date: Wed, 04 Jan 2023 17:52:29 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 10
Connection: keep-alive
Apple-Failure-Details: {"cause":"invalid character '/' looking for beginning of value"}
Apple-Failure-Reason: SWCERR00401 Bad JSON content
Please someone help me to understand what is wrong with this JSON
{
"applinks": {
"details": [
{
"appIDs": [
"teamID.com.app.menu" //example
],
"components": [
{
"/": "/*",
"comment": "Matches any URL whose path starts with /"
},
{
"/": "/contact-us/*",
"exclude": true,
"comment": "Matches any URL whose path starts with /contact-us/ and instructs the system not to open it as a universal link"
}
]
}
]
},
"appclips": {
"apps": [
]
}
}
Links redirected when I added this mode on the simulator
Remove //example from your JSON.

Add default headers for every request in httpie

I need to be able to either set in my httpie/config.json file to include some default headers (these are custom headers and not normal ones) to every request that i send from httpie by default (ALWAYS)
ie:
headers examples
http "http://poopskiesuprise.com" 'CUSTOM_HEADER:asdf' 'HEADER_TWO:asdf'
always include the 'CUSTOM_HEADER' and 'HEADER_TWO'
to every request so i can just do this
http "http://poopskiesuprise.com"
i did not see a good way to do this in the documentation so any help would be great!
The easiest solution is creating a session with desired headers, and using it on your config.json:
Create a session (for your desired host):
$ http --session ./session.json pie.dev/get X-Custom-Header:value X-Custom-Header2:value2
and then add this to your config (~/.config/httpie/config.json on POSIX):
{
"default_options": [
"--session-read-only=/path/to/session.json"
]
}
and then from now on, every request will add those two headers:
$ http pie.dev/get
{
"args": {},
"headers": {
"X-Custom-Header": "value",
"X-Custom-Header2": "value2"
},
"url": "http://pie.dev/get"
}
Unless you unset them:
$ http pie.dev/get X-Custom-Header:
{
"args": {},
"headers": {
"X-Custom-Header2": "value2"
},
"url": "http://pie.dev/get"
}

Drive item size is wrong after upload of plain text file to OneDrive

When uploading files to OneDrive for Business using the Graph API I sometimes see that the drive item has the wrong size after the PUT request. I know that OneDrive might modify Office files on the fly but I see it happening for plain text files too.
In example below I write the string first version (13 bytes) to a new drive item.
PUT https://graph.microsoft.com/v1.0/drives/b!e8-Jy2tSiUy2AJBZzvZxc3DIh8dRoG9DrM6MEcF_oxinj1yhH9A8RYDHeCfkxipc/items/root:/onedrive-public-kuvgpshldglnfidf.
txt:/content
Don't think it matters but I set the Content-Type header to application/octet-stream. Graph API returns status code 201 (as expected) and the response:
{
"#odata.context": "https:\/\/graph.microsoft.com\/v1.0\/$metadata#drives('b%21e8-Jy2tSiUy2AJBZzvZxc3DIh8dRoG9DrM6MEcF_oxinj1yhH9A8RYDHeCfkxipc')\/items\/$entity",
"#microsoft.graph.downloadUrl": "https:\/\/REDACTED.sharepoint.com\/sites\/go-test-onedrive-kuvgpshldglnfidf\/_layouts\/15\/download.aspx?UniqueId=ce025490-d7ee-438a-ac00-a817784e7ea7&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvemVid2FyZXRlc3Quc2hhcmVwb2ludC5jb21AYzBkYjg4MTAtZGZjOS00ODM5LTgyMzQtNTkzNjQwODUzZWQyIiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTU5OTQ2Mjc3MyIsImV4cCI6IjE1OTk0NjYzNzMiLCJlbmRwb2ludHVybCI6IktpSTJyNGo0MVN3MnJhQlVRNG90Mmo1bzIrMEdtbVJBV1grYWNEQzg0bVk9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxNjIiLCJpc2xvb3BiYWNrIjoiVHJ1ZSIsImNpZCI6Ik1tVmtOMk0zWVdJdE5EY3dOaTAwWmpjMExXRmpZMll0TVdFM09ESmtPV1V4TkRFMyIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJZMkk0T1dObU4ySXROVEkyWWkwMFl6ZzVMV0kyTURBdE9UQTFPV05sWmpZM01UY3oiLCJhcHBfZGlzcGxheW5hbWUiOiJPcmNoZXN0by0zNjUtMjAyMDA0MjAiLCJuYW1laWQiOiI5YzU1NzQ0OS1mMmY1LTRjNzMtYTYzOC04MThlYjg2YWFkOThAYzBkYjg4MTAtZGZjOS00ODM5LTgyMzQtNTkzNjQwODUzZWQyIiwicm9sZXMiOiJncm91cC5yZWFkIGdyb3VwLndyaXRlIGFsbGZpbGVzLndyaXRlIGFsbHByb2ZpbGVzLnJlYWQiLCJ0dCI6IjEiLCJ1c2VQZXJzaXN0ZW50Q29va2llIjpudWxsfQ.Nm1lSTJML0U1N2dVSzZ2L2MwbkVoc3Fnc0pkbk4wZ0psM1FsWFArWHdTND0&ApiVersion=2.0",
"createdDateTime": "2020-09-07T07:13:03Z",
"eTag": "\"{CE025490-D7EE-438A-AC00-A817784E7EA7},1\"",
"id": "013OPAMZEQKQBM53WXRJB2YAFIC54E47VH",
"lastModifiedDateTime": "2020-09-07T07:13:03Z",
"name": "onedrive-public-kuvgpshldglnfidf.txt",
"webUrl": "https:\/\/REDACTED.sharepoint.com\/sites\/go-test-onedrive-kuvgpshldglnfidf\/Delade%20dokument\/onedrive-public-kuvgpshldglnfidf.txt",
"cTag": "\"c:{CE025490-D7EE-438A-AC00-A817784E7EA7},1\"",
"size": 26,
"createdBy": {
"application": {
"id": "9c557449-f2f5-4c73-a638-818eb86aad98",
"displayName": "REDACTED"
}
},
"lastModifiedBy": {
"application": {
"id": "9c557449-f2f5-4c73-a638-818eb86aad98",
"displayName": "REDACTED"
}
},
"parentReference": {
"driveId": "b!e8-Jy2tSiUy2AJBZzvZxc3DIh8dRoG9DrM6MEcF_oxinj1yhH9A8RYDHeCfkxipc",
"driveType": "documentLibrary",
"id": "013OPAMZF6Y2GOVW7725BZO354PWSELRRZ",
"path": "\/drives\/b!e8-Jy2tSiUy2AJBZzvZxc3DIh8dRoG9DrM6MEcF_oxinj1yhH9A8RYDHeCfkxipc\/root:"
},
"file": {
"mimeType": "text\/plain",
"hashes": {
"quickXorHash": "ZkiDHOZABxDYoQxylUMa3uAGAAA="
}
},
"fileSystemInfo": {
"createdDateTime": "2020-09-07T07:13:03Z",
"lastModifiedDateTime": "2020-09-07T07:13:03Z"
}
}
Notice how drive item size is 26 and not 13 as expected. The drive item size is still 26 if I fetch the drive item using a GET request. If I follow the download URL I get the correct Content-Length header though:
$ curl -v -H "Authorization: bearer $TOKEN" $DOWNLOADURL
...
< HTTP/2 200
< cache-control: private
< content-length: 13
< content-type: text/plain
...
first version
Is it possible to get the correct drive item size directly without having to check the Content-Length header when following the download URL?
Once you upload the file in the OneDrive, then it will add additional metadata to Office documents after you upload (not the file types though). I remember a related thread on this, discussing about this - link.

how to get an openstack token and validate it?

I followed this guide: http://keystone.openstack.org/api_curl_examples.html
and it seemed that I got a valid token by ran:
curl -d '{"auth":{"passwordCredentials":{"username": "can", "password": "mypassword"}}}' -H "Content-type: application/json" http://url:35357/v2.0/tokens
and it returned:
{
"access":
{
"token":
{
"expires": "2012-05-21T14:35:17Z",
"id": "468da447bd1c4821bbc5def0498fd441"
},
"serviceCatalog": {},
"user":
{
"username": "can",
"roles_links": [],
"id": "bb6d3a09ad0c4924bf20c1a32ccb5781",
"roles": [],
"name": "can"
}
}
}
but when I came to the next few sections to validate this token, I encountered this magic number: X-Auth-Token:999888777666. At first I thought it's the token I got but I was wrong.
I think I may have missed something, so I read related sections in openstack documents( http://keystone.openstack.org/configuration.html and http://docs.openstack.org/api/openstack-compute/programmer/content/ ), but still no idea how the number comes from.
could anyone explain to me
what's the meaning of that magic number
how to get the right value of it so I can get a working token to manage other parts of openstack
That magic number (string really) is the admin_token setting in your keystone.conf file. Under the [DEFAULT] section in keystone.conf set
admin_token = abcd1234
If you don't use it for admin actions, you'll see something like
ubuntu#i-000004bc:~/devstack$ curl http://localhost:35357/v2.0/tenants
{"error": {"message": "The request you have made requires authentication.", "code": 401, "title": "Not Authorized"}}
If you do use it, you'll see something like
ubuntu#i-000004bc:~/devstack$ curl -H "X-Auth-Token: abcd1234" http://localhost:35357/v2.0/tenants
{"tenants_links": [], "tenants": [{"enabled": true, "description": null, "name": "demo", "id": "aee8a46babcb4e4286021c8f6ef996cd"}, {"enabled": true, "description": null, "name": "invisible_to_admin", "id": "de17fea45de148ada0a58e998e6c3e73"}, {"enabled": true, "description": null, "name": "admin", "id": "f34b0c8ab30e450489b121fbe723fde5"}, {"enabled": true, "description": null, "name": "service", "id": "fbe3e2e530fd47298cb2cba1b4afa3da"}]}
To get the list of tenants, in our current implementation, we authenticate with admin credentials and use the token returned to get list of tenants.
The implementation works smooth with the authentication token. It may work with admin_token but I have not verified.
If you see the examples you are referring to, there are 2 types of endpoints used
Endpoint pointing to port 5000 - public port
Endpoint pointing to port 35357 - admin port
In examples which are hitting admin port you would need to specify the "X-Auth-Token" header as the admin_token (specified in the keystone.conf file)
The token itself is in dict["access"]["token"]["id"] which is that part that will go in the header of subsequent HTTP requests, i.e
X-Auth-Token: 468da447bd1c4821bbc5def0498fd441
The value 999888777666 is from the curl example tutorial and will definitely not work.
As for the value of the token itself, it's randomly generated by the OpenStack service and shouldn't contain any useful information from your point of view.
(BTW, you probably shouldn't go pasting the tokens into forums as they're valid for 24 hours and anyone with a copy of the token and access to your compute endpoint can use it to impersonate you).

Resources