<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://blog.fajfer.org" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>fajfer.org</title>
    <link>https://blog.fajfer.org/pl/feed.xml</link>
    <atom:link href="https://blog.fajfer.org/pl/feed.xml" rel="self" type="application/rss+xml"/>
    <description>Polski</description>
    <language>pl</language>
    
    
      
      <item>
        <title>Serwowanie stron z gita i bezpieczeństwo</title>
        <link>https://blog.fajfer.org/pl/blog/dotgit/</link>
        <description>&lt;p&gt;Przeczytałem kiedyś na &lt;a href=&quot;https://niebezpiecznik.pl/post/incydent-w-sklepie-weroniki-sowy-wersow-com-dane-osobowe-byly-dostepne-publicznie/&quot;&gt;Niebezpieczniku&lt;/a&gt; artykuł o wycieku w sklepie influencerki Wersow. Artykuł zainspirował mnie przede wszystkim do zainstalowania wtyczki &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/dotgit/&quot;&gt;DotGit&lt;/a&gt;, ale do tej pory nie udało mi się znaleźc niczego spektakularnie ciekawego. Ot, proste strony statyczne czy kod, który i tak jest publiczny. Do dziś wątpiłem, że ktoś na serio wrzuciłby kredki do gita na prywatne repozytorium a potem rzucał &lt;code&gt;git pull&lt;/code&gt; do synchronizacji w tym samym repozytorium.&lt;/p&gt;
&lt;p&gt;Wyprzedzając pytania - administrator został powiadomiony i wpis został umieszczony już po naprawieniu problemu.&lt;/p&gt;
&lt;h2&gt;Od .git/config do haseł&lt;/h2&gt;
&lt;p&gt;Serfując po internecie z wyżej wymienioną wtyczką dostaniemy &lt;em&gt;popup&lt;/em&gt; o znalezionym repozytorium &lt;code&gt;.git&lt;/code&gt;, adresy zbierają się też w samym narzędziu więc można co jakiś czas spojrzeć co udało się przypadkowo zebrać. Spróbujmy wyciągnąć z tego coś sensownego.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/dotgit/dotgit.png&quot; alt=&quot;Dotgit download all tooltip&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;Poręczna funkcjonalność&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Pobieramy repozytorium przez wtyczkę, wypakowujemy, przechodzimy do katalogu i możemy zobaczyć, że jest pusty. Po wpisaniu polecenia &lt;code&gt;git status&lt;/code&gt; widać jednak jakie pliki są usunięte:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;On branch master
Your branch is based on &lt;span class=&quot;token string&quot;&gt;&#39;origin/master&#39;&lt;/span&gt;, but the upstream is gone.
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;token string&quot;&gt;&quot;git branch --unset-upstream&quot;&lt;/span&gt; to fixup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Changes not staged &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; commit:
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;token string&quot;&gt;&quot;git add/rm &amp;lt;file&gt;...&quot;&lt;/span&gt; to update what will be committed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;token string&quot;&gt;&quot;git restore &amp;lt;file&gt;...&quot;&lt;/span&gt; to discard changes &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; working directory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        deleted:    .gitignore
        deleted:    .htaccess
        deleted:    .htpasswd
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

no changes added to commit &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;token string&quot;&gt;&quot;git add&quot;&lt;/span&gt; and/or &lt;span class=&quot;token string&quot;&gt;&quot;git commit -a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git służy do przechowywania historii zmian. Poprzednie commity są w formacie binarnym, w najprostszy sposób możemy dotrzeć do nich używając polecenia &lt;code&gt;git restore .&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-a&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;     .gitignore  admin     assets      &lt;span class=&quot;token function&quot;&gt;cron&lt;/span&gt;         index.php   mediacacheAdv            modules     static
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;    .htaccess   admin321  class       css          js          mediacacheArticle        resource    templates
.git  .htpasswd   ajax.php  config.php  imagick.php  mediaCache  mediacachePhotorelation  robots.txt  tmp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jak widać powyżej, pliki się odtworzyły. Pomijając hasła wpisane na sztywno w skryptach. Możemy nawet udać na potrzeby edukacyjne, że ich nie było. Najbardziej zaciekawił mnie plik &lt;code&gt;.htpasswd&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/dotgit/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Byłem ciekaw, czy uda mi się odgadnąć hasło do znalezionego użytkownika. Przykład jest zmyślony, ale ciąg zdarzeń analogiczny. Dla poniższego wpisu w &lt;code&gt;.htpasswd&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin:6YPqJe88Wz5fQ&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Napisałem &lt;em&gt;snippet&lt;/em&gt; w Pythonie i dopisałem kilka propozycji dla powyższego użytkownika, (chciałem chwilę później spróbować metodą słownikową) wyglądało to mniej więcej tak:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; crypt

passwords &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;admin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;123456&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;admin123&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;6YPqJe88Wz5fQ&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; password &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; passwords&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; crypt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;crypt&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Password found: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Password not found in common list&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Po uruchomieniu dostałem potwierdzenie:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ python3 htpasswd.py 
Password found: admin123&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Co stało się dalej?&lt;/h2&gt;
&lt;p&gt;Po moim zgłoszeniu część rzeczy została ukryta w taki sposób:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/dotgit/forbidden.png&quot; alt=&quot;403 Forbidden z serwera Apache2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Tu się będę już czepiał, ale chcę pokazać dlaczego jawna wersja oprogramowania w komunikacie błędu daje atakującemu nadmierną ilość informacji. Powyższa wersja Apache2 wskazuje prawdopodobnie na Ubuntu 22.04 LTS (jammy). Dlaczego? Bo ostatnia najnowsza wersja z Ubuntu 20.04 LTS (focal) to 2.4.41&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/dotgit/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;, natomiast w jammy już 2.4.52&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/dotgit/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;. Najnowszy commit również wskazywałby, że strona nie jest juz jakiś czas aktualizowana&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/dotgit/commit.png&quot; alt=&quot;Najnowszy znaleziony commit&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Wnioski&lt;/h2&gt;
&lt;p&gt;Ogromna prośba, żeby nie trzymać w gicie jawnie haseł. To nie jest odpowiednie miejsce. Jak widać, nawet w przypadku korzystania z prywatnego repozytorium coś po drodze może pójść nie tak i hasła mogą wyciec.&lt;/p&gt;
&lt;meta name=&quot;fediverse:creator&quot; content=&quot;@fajfer@mastodon.social&quot; /&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://pl.wikipedia.org/wiki/.htpasswd&quot;&gt;https://pl.wikipedia.org/wiki/.htpasswd&lt;/a&gt; Dostęp 19.02.2026 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/dotgit/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://launchpad.net/ubuntu/focal/+source/apache2&quot;&gt;https://launchpad.net/ubuntu/focal/+source/apache2&lt;/a&gt; Dostęp 19.02.2026 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/dotgit/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://packages.ubuntu.com/jammy/apache2&quot;&gt;https://packages.ubuntu.com/jammy/apache2&lt;/a&gt; Dostęp 19.02.2026 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/dotgit/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Thu, 19 Feb 2026 02:03:00 +0000</pubDate>
        <dc:creator>Damian Fajfer</dc:creator>
        <guid>https://blog.fajfer.org/pl/blog/dotgit/</guid>
      </item>
      
    
    
      
      <item>
        <title>Running Green Cell UPS app (GCUPS) on GNU/Linux server</title>
        <link>https://blog.fajfer.org/pl/blog/gcups/</link>
        <description>&lt;p&gt;If you&#39;re one of these people you probably also want/need an UPS. Since I&#39;m installing a data box I&#39;ve been searching for an UPS to support the rest of my 11&amp;quot; rack and couldn&#39;t really find anything appealing to me on the local market from APC. After some research I realized that I would love to have an exchangeable battery so I&#39;ve acquired a Green Cell UPS in the process. They advertised a dedicated software that comes with it but it didn&#39;t really matter to me until I&#39;ve discovered that it supports several GNU/Linux distributions.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/gcups/eon.jpg&quot; alt=&quot;Cosign signature in Artifactory&quot; /&gt;&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/gcups/ups.webp&quot; alt=&quot;Cosign signature in Artifactory&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;I like how Green Cell UPS looks similar to the EON from the video game Original War&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;GC UPS App&lt;/h2&gt;
&lt;p&gt;On their &lt;a href=&quot;https://gcups.greencell.global/en&quot;&gt;download page&lt;/a&gt; (edit: or my &lt;a href=&quot;https://github.com/fajfer/gcups&quot;&gt;GitHub&lt;/a&gt;) they offer gcups (that&#39;s how it&#39;s called) for all modern desktop systems - Windows, MacOS and, surprisingly, Linux support for .deb, .rpm, .pacman and .tar.gz (with some shell scripts). There&#39;s a pretty solid multi-platform choice as they are using Electron running on Chromium. The worst thing is that this software isn&#39;t open source.&lt;/p&gt;
&lt;p&gt;All in all, Linux support convinced me to give it a try. I&#39;m not going to do much of a review of it. Once I ran some successful tests via webGUI I thought that it could be useful to run it, just not on my desktop. I&#39;ve tried running gcups with some parameters to demonize it but to no avail. At the time of writing this article I&#39;m using version 1.1.7 released 02.06.2023. Running gcups on my server gave me this output:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ gcups 
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;371031&lt;/span&gt;:0915/014627.729749:ERROR:ozone_platform_x11.cc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Missing X server or &lt;span class=&quot;token environment constant&quot;&gt;$DISPLAY&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;371031&lt;/span&gt;:0915/014627.729793:ERROR:env.cc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; The platform failed to initialize.  Exiting.
Segmentation fault &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;core dumped&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/gcups/gc-odp.png&quot; alt=&quot;Cosign signature in Artifactory&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;Support replying to me that there is no way to run gcups without the GUI, let&#39;s prove them wrong&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Running gcups in CLI environment&lt;/h2&gt;
&lt;p&gt;Searching for some information on running gcups didn&#39;t get me anywhere (version 1.0.0 was published in June 2022) so I started tinkering a bit. Even if I went as far (or as near) as getting this running without X server I&#39;d still need to enable HTTP server in the application settings. I&#39;ve been doing the usual stuff but I didn&#39;t notice any new processes starting up if I enable the web server, &lt;code&gt;strings&lt;/code&gt; didn&#39;t give me any insightful output non-specific to Chromium, I couldn&#39;t find anything in the &lt;code&gt;~/.config/gcups&lt;/code&gt; either. There is also an &lt;code&gt;/opt/gcups&lt;/code&gt; directory being created during the install so I&#39;ve eventually began searching in the db folder and - hooray - this was the place.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;/opt/gcups/db$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt;
gcups-rxdb-0-                                                           gcups-rxdb-0-scheduler-mrview-c37be66b94b0bdae91ef3fcbeab58edf
gcups-rxdb-0-device_parameters                                          gcups-rxdb-0-settings-local
gcups-rxdb-0-device_parameters-local                                    gcups-rxdb-0-test
gcups-rxdb-0-device_parameters-mrview-99560a34de60f5074dcd2be42069d585  gcups-rxdb-0-test-local
gcups-rxdb-0-register                                                   gcups-rxdb-0-test-measurement
gcups-rxdb-0-register-local                                             gcups-rxdb-0-test-measurement-local
gcups-rxdb-0-register-mrview-692a6698c32319395128b449dfae271e           gcups-rxdb-0-test-measurement-mrview-99560a34de60f5074dcd2be42069d585
gcups-rxdb-0-_rxdb_internal                                             gcups-rxdb-0-test-mrview-8b2440dfbb354345cc5c69a011a2beb9
gcups-rxdb-0-scheduler                                                  gcups-rxdb-0-test-mrview-8b851648c605dcf349b861f65fdffef5
gcups-rxdb-0-scheduler-local                                            gcups-rxdb-1-settings  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;--- this is the one that&#39;s interesting to us
gcups-rxdb-0-scheduler-mrview-2f6b156c4b77dd00407dbed941ee1abf          pouch__all_dbs__&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;ve accessed gcups-rxdb-1-settings database using LevelDB via python:&lt;/p&gt;
&lt;pre class=&quot;language-python3&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python3&quot;&gt;import plyvel
db = plyvel.DB(&#39;/opt/gcups/db/gcups-rxdb-1-settings&#39;)

for key, value in db:
    print(f&quot;{key.decode()}: {value.decode()}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives us an interesting output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ÿby-sequenceÿ0000000000000001: {&amp;quot;api&amp;quot;:{&amp;quot;port&amp;quot;:8080,&amp;quot;password&amp;quot;:&amp;quot;password hash here&amp;quot;,&amp;quot;enable&amp;quot;:true,&amp;quot;salt&amp;quot;:&amp;quot;password salt here&amp;quot;},&amp;quot;_attachments&amp;quot;:{},&amp;quot;_id&amp;quot;:&amp;quot;a733f0a7-4fe2-4120-8603-775370fd871a&amp;quot;,&amp;quot;_rev&amp;quot;:&amp;quot;12-c2e2e2d475614a9aed42806e63a38338&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To break up the most interesting parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;port&lt;/strong&gt; is pretty obvious, this is just an HTTP port for our webserver&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;enable&lt;/strong&gt; tells us if the HTTP server is enabled by default on gcups run&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I found is that you can actually just replace the first and only sequence for gcups to work. There&#39;s a (4th from the end) key called &lt;code&gt;document-store&lt;/code&gt; which stores all revs of the previous sequences as well as the &lt;code&gt;winningRev&lt;/code&gt; but only the &lt;code&gt;seq&lt;/code&gt; value matters in this case, which is in most cases your last &lt;code&gt;by-sequence&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Generating your own by-sequence&lt;/h2&gt;
&lt;p&gt;Now that we know how to access gcups settings without running the gcups itself we need to replace port (optionally), enabled, password and salt. I don&#39;t know how to generate salt and password by hand so I&#39;d recommend installing gcups locally, configuring it and then exporting this setting to your server. &lt;strong&gt;Keep in mind, that you can&#39;t change your password from the webGUI&lt;/strong&gt;. To do this simply install gcups locally, set the password up and enable HTTP server in the settings. Afterwards proceed to &lt;code&gt;/opt/gcups/db/gcups-rxdb-1-settings&lt;/code&gt; and perform PUT on your data:&lt;/p&gt;
&lt;pre class=&quot;language-python3&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python3&quot;&gt;import plyvel
db = plyvel.DB(&#39;/opt/gcups/db/gcups-rxdb-1-settings&#39;)

db.put(b&#39;&#92;xc3&#92;xbfby-sequence&#92;xc3&#92;xbf0000000000000001&#39;, b&#39;{&quot;api&quot;:{&quot;port&quot;:8080,&quot;password&quot;:&quot;password hash here&quot;,&quot;enable&quot;:true,&quot;salt&quot;:&quot;password salt here&quot;},&quot;_attachments&quot;:{},&quot;_id&quot;:&quot;a733f0a7-4fe2-4120-8603-775370fd871a&quot;,&quot;_rev&quot;:&quot;12-c2e2e2d475614a9aed42806e63a38338&quot;}&#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You don&#39;t need to do anything else now. I&#39;ve mimicked xserver by using &lt;code&gt;xvfb&lt;/code&gt; and it enables you to run gcups on your server this way:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xvfb-run gcups&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Afterwards, you can access your gcups webGUI on the &lt;code&gt;host:port&lt;/code&gt; on your server you specified in the &lt;code&gt;by-sequence&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;I&#39;ve contacted the support two times to confirm that the software is not supposed to work without GUI. There is going to be a purely cli solution for gcups and it&#39;s on the Green Cell&#39;s roadmap but it is unknown when it&#39;s going to be released which made me spend one evening trying to run it non-intended way.&lt;/p&gt;
&lt;p&gt;I&#39;m thinking about containerization of the complete solution sometime this year, I will update the blogpost afterwards and provide a ready docker-compose with USB passthrough to the container (UPS connects via USB to the machine for gcups to be functional). It would be cool if I also learned how to generate pass/salt combination for gcups as I haven&#39;t given it much thought.&lt;/p&gt;
&lt;p&gt;And last but not least - there is no point for such software to &lt;strong&gt;NOT&lt;/strong&gt; be free software. The only meaningful thing this would expose would be communication scheme between the software and the UPS. So what? Every UPS manufacturer communicates to his UPS in a different way as there is no general protocol on how it should be done. I don&#39;t think that it&#39;s much of a secret and that it eventually couldn&#39;t be exposed with some work anyway. Even if gcups would be free and people decided to use non-Green Cell developed solutions it would still be beneficial for Green Cell as, because of the different communication schemes, these 3rd party solutions would still only support their product.&lt;/p&gt;
&lt;p&gt;Now that it&#39;s closed source my work was focused on bypassing xserver requirement instead of making their product better and their product wouldn&#39;t exist if not for open source anyway.&lt;/p&gt;
&lt;h2&gt;UPDATE 03.04.2024&lt;/h2&gt;
&lt;p&gt;Hey guys! Motivated by comments from Robert I managed to dockerize the above solution. There&#39;s still some work but I&#39;m willing to take it on and maintain the project.&lt;/p&gt;
&lt;p&gt;https://github.com/fajfer/gcups&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker pull ghcr.io/fajfer/gcups:1.1.7&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;UPDATE 19.08.2024&lt;/h2&gt;
&lt;p&gt;Due to popular demand I&#39;ve created a Matrix chat room so I can aid you at a whim (or a bit later) - https://matrix.to/#/#gcups:fsfe.org&lt;/p&gt;
&lt;meta name=&quot;fediverse:creator&quot; content=&quot;@fajfer@mastodon.social&quot; /&gt;
</description>
        <pubDate>Sat, 16 Sep 2023 14:00:00 +0000</pubDate>
        <dc:creator>Damian Fajfer</dc:creator>
        <guid>https://blog.fajfer.org/pl/blog/gcups/</guid>
      </item>
      
    
    
    
    
      
      <item>
        <title>Cosign signatures lifecycle in Artifactory</title>
        <link>https://blog.fajfer.org/pl/blog/cosign-artifactory/</link>
        <description>&lt;p&gt;Additionally, we&#39;ll delve into a proposed solution for copying the signature to a target repository during artifact promotion or copying phases, addressing potential challenges in the process.&lt;/p&gt;
&lt;p&gt;Details regarding signing and verifying docker containers won&#39;t be covered in this blog post. This has been very well explained in other people blog posts&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;, as well as in the official documentation&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;. It&#39;s safe to say that it works since at least 2021.&lt;/p&gt;
&lt;h2&gt;Working with Artifactory&lt;/h2&gt;
&lt;p&gt;Before going on with signing we need to authenticate ourselves to the docker registry. I&#39;m using Artifactory docker registry&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; as an example in this scenario.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cosign login &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{{ password }}&#39;&lt;/span&gt; x.artifactory.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cosign could return an error if you provide an URL with the schema:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: registries must be valid RFC 3986 URI authorities: https://x.artifactory.com
main.go:74: error during command execution: registries must be valid RFC 3986 URI authorities: https://x.artifactory.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a solution simply omit the schema (https:// in the above example).&lt;/p&gt;
&lt;p&gt;When cosign has successfully logged in, build and push the image as usual. Afterwards, you should sign your docker image using cosign sign. If you did everything right to this point, executing cosign verify as a sanity check on the same machine will provide the following output:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cosign verify &lt;span class=&quot;token parameter variable&quot;&gt;--key&lt;/span&gt; cosign.pub x.artifactory.com/fajfer/image:example
The following checks were performed on these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Critical&quot;&lt;/span&gt;:&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Identity&quot;&lt;/span&gt;:&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;docker-reference&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;,&lt;span class=&quot;token string&quot;&gt;&quot;Image&quot;&lt;/span&gt;:&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Docker-manifest-digest&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sha256:87ef60f558bad79beea6425a3b28989f01dd417164150ab3baab98dcbf04def8&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;,&lt;span class=&quot;token string&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cosign container image signature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;,&lt;span class=&quot;token string&quot;&gt;&quot;Optional&quot;&lt;/span&gt;:null&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can repeat the command on a different machine to verify that the signature has been successfully uploaded. The output should remain the same and the signature should be visible in the webUI:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/cosign-artifactory/sig.png&quot; alt=&quot;Cosign signature in Artifactory&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;So what&#39;s the problem?&lt;/h2&gt;
&lt;p&gt;As per documentation:&lt;/p&gt;
&lt;p&gt;Cosign documentation @ af555d5&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Signatures are stored as separate objects in the OCI registry, with only a weak reference back to the object they &amp;quot;sign&amp;quot;. This means this relationship is opaque to the registry, and signatures will not be deleted or garbage-collected when the image is deleted. Similarly, they can easily be copied from one environment to another, but this is not automatic.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your artifact lifecycle ends here and images from here are being deployed to production or are available to public then that&#39;s it, you&#39;re done. Otherwise, if you want to promote your images or copy them somewhere else then you&#39;ll notice that while your artifacts are getting promoted to the target repository, their signatures are left intact in the source repository. Which means that if you build and sign artifacts in the repository x, then after promoting it to repository y cosign will give you this sad response:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cosign verify &lt;span class=&quot;token parameter variable&quot;&gt;--key&lt;/span&gt; cosign.pub y.artifactory.com/fajfer/image:example
Error: no matching signatures:

main.go:52: error during &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; execution: no matching signatures:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What&#39;s wrong, right? It just worked perfectly in the old repository.&lt;/p&gt;
&lt;h2&gt;The proposed solution&lt;/h2&gt;
&lt;p&gt;We need to copy the signature to the target repository. After the Promote Docker Image REST API request we need to do a Copy Item request to copy the signature. There&#39;s an important detail here - cosign names the signature after SHA256 of manifest.json of our image. Luckily, we can easily access that information by executing File Info request. We can also calculate this ourselves but I assume you don&#39;t have the image locally anymore during the promotion/copy phase.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.fajfer.org/img/blog/cosign-artifactory/example.png&quot; alt=&quot;Digest field under &#39;Docker Info&#39; in the UI also displays the hash&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To understand the solution better and get an idea of how your requests should look like, here&#39;s an example in Ansible code that could be used to implement a solution in your CI system:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Promote Docker Image
  &lt;span class=&quot;token comment&quot;&gt;# https://jfrog.com/help/r/jfrog-rest-apis/promote-docker-image&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ artifactory_url }}/api/docker/{{ source_repo }}/v2/promote&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; POST
    &lt;span class=&quot;token key atrule&quot;&gt;url_username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ username }}&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;url_password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ password }}&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;force_basic_auth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;body_format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; json
    &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;targetRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ target_repo }}&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;dockerRepository&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ docker_repository }}&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Get manifest.json (File Info)
  &lt;span class=&quot;token comment&quot;&gt;# https://jfrog.com/help/r/jfrog-rest-apis/file-info&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &quot;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; artifactory_url &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/api/storage/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; source_repo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/&#92;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; file_path &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tag &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/manifest.json&quot;
    &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GET
    &lt;span class=&quot;token key atrule&quot;&gt;url_username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ username }}&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;url_password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ password }}&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;force_basic_auth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; manifest

&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Copy cosign signature (Copy Item)
  &lt;span class=&quot;token comment&quot;&gt;# https://jfrog.com/help/r/jfrog-rest-apis/copy-item&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &quot;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; artifactory_url &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/api/copy/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; source_repo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/&#92;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; source_file_path &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/sha256&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; manifest.json.checksums.sha256 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;.sig&#92;
      &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt;to=/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; target_repo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; target_file_path &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&quot;
    &lt;span class=&quot;token key atrule&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; POST
    &lt;span class=&quot;token key atrule&quot;&gt;url_username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ username }}&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;url_password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ password }}&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;force_basic_auth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach makes the best use of Artifactory&#39;s API and doesn&#39;t require the image and signature to be downloaded locally at all.&lt;/p&gt;
&lt;h2&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;Cosign support of Artifactory is very well done and the Artifactory knows that it serves you signed images as it sends you a signature along with the container after executing docker pull. The API doesn&#39;t reflect that though, but that&#39;s hopefully going to change in the future. Container signing becomes more popular and more accessible thanks to tools like cosign, notary and kyverno to name a few so doing workarounds like this shouldn&#39;t be required in the future.&lt;/p&gt;
&lt;meta name=&quot;fediverse:creator&quot; content=&quot;@fajfer@mastodon.social&quot; /&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Jabar Asadi, &amp;quot;Digital Signature With Cosign&amp;quot; May 4, 2023. https://eng.d2iq.com/blog/digital-signature-with-cosign/ Accessed 22.07.2023 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Sigstore, &amp;quot;Signing Containers&amp;quot; https://docs.sigstore.dev/cosign/signing_with_containers/ GitHub: 18b11e2 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Sigstore, &amp;quot;Verifying&amp;quot; https://docs.sigstore.dev/cosign/verify GitHub: 4186c93 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;JFrog Artifactory Documentation, &amp;quot;Docker Registry&amp;quot; https://jfrog.com/help/r/jfrog-artifactory-documentation/docker-registry Accessed: 23.07.2023 &lt;a href=&quot;https://blog.fajfer.org/pl/blog/cosign-artifactory/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Sun, 23 Jul 2023 14:00:00 +0000</pubDate>
        <dc:creator>Damian Fajfer</dc:creator>
        <guid>https://blog.fajfer.org/pl/blog/cosign-artifactory/</guid>
      </item>
      
    
    
    
  </channel>
</rss>
