toudi / ksef

program do generowania i wysyłki efaktur (Krajowy System eFaktur)
http://ksef.po-godzinach.info
13 stars 2 forks source link

save-token #2

Closed kuncy7 closed 11 months ago

kuncy7 commented 1 year ago

Fajny projekt, ale zakłada że system (linux) używa dbus i gnome-keyring. Mam taki problem ze starszym sytemem i takim bez desktopa, np. czysty ubuntu server:

./ksef save-token -t -nip 9999999999 -token E71A51F77xxxxxxxxxxxxxxxxxxxxxxxxxxxx
error running save-token:
The name org.freedesktop.secrets was not provided by any .service files

Jest alternatywny sposób przechowywania tokena?

toudi commented 1 year ago

o rany przepraszam, nie dostałem żadnego powiadomienia o stworzonym tickecie. poczytam o tym

kuncy7 commented 1 year ago

Tak sprawdziłem, to na takich czystych i starych systemach dostępna jest komenda keyctl, może się jakoś nada to tego projektu.

[edit] Ja dostałem powiadomienie, nie mam pojęcia czemu autor projektu nie dostał??

toudi commented 1 year ago

znalazłem jeszcze taki wpis: https://unix.stackexchange.com/questions/473528/how-do-you-enable-the-secret-tool-command-backed-by-gnome-keyring-libsecret-an

znalazłem też informację, że można używać gnome-keyring w trybie headless (switch --daemon) oraz że można użyć keepassxc jako dostarczyciela org.freedesktop.secrets tylko że tam też trzeba gdzieś wpisać hasło. z tego co rozumiem zaletą gnome-keyring jest to że kiedy się zaloguje do konta to powoduje to automatyczne odblokowanie keyringa. czyli pewnie tak samo mogłoby być w przypadku serwera headless bo i tak żeby uruchomić program ksef trzebaby to zrobić np. przez ssh

muszę zainstalować wirtualkę z ubuntu-server i wtedy będę mógł to potwierdzić (tzn konkretnie to czy instalacja gnome-keyring nie pociągnie za sobą instalacji kosmicznych zależności i całego pakietu gnome). niestety robię to wszystko po godzinach a jednocześnie czekam na odpowiedź na kilka pytań z ministerstwa finansów więc to wszystko wygląda tak jak wygląda :/ z góry przepraszam i proszę o wyrozumiałość

też nie mam pojęcia czemu nie dostałem powiadomienia, ale Twoją odpowiedź już dostałem na maila :) będę miał nauczkę na przyszłość żeby cyklicznie to sprawdzać :)

toudi commented 1 year ago

na podstawie google udało mi się wykombinować taki krótki przykład:

toudi@x300:~> keyctl newring ksef @u
[idendytikator keyringu]
toudi@x300:~> keyctl add user test ttteeesssttt %:ksef
[identyfikator klucza 'test' w keyringu 'ksef']
toudi@x300:~> keyctl print [identyfikator klucza 'test' w keyringu 'ksef']
ttteeesssttt

można tez użyć komendy keyctl show żeby zweryfikować, że keyring istnieje. muszę tylko wykombinować jak to wszystko pożenić - najprawdopodobniej odczytać błąd z paczki która obsługuje keyring

kuncy7 commented 1 year ago

Właśnie próbowałem instalować gnome-keyring (który wymaga dbus-x11) i miałem problemy z "odblokowaniem" dostępu, pewnie to akurat jest do rozwiązania. Niestety próba zainstalowania tych pakietów na starszym systemie skończyła się tak że po zalogowaniu przez ssh terminal "umierał", nic nie dało się wpisać. Musiałem uruchomić linux w trybie single i zablokować start dbus. Dlatego w pierwszym wpisie pytam o alternatywny sposób przechowywania tokena. Jak by się udało zaimplementować uzycie keyctl byłoby świetnie.

Bardzo doceniam to co tutaj zostało zrobione, to najbardziej kompletny klient do ksef jaki znalazłem i najmniej skomplikowany w użyciu. Próbowałem też wersji w pythonie i tam np. pogubiłem się z zależnościami i wersjami python vs vpython . Tak więc, nie mam za co przepraszać, trzymam kciuki!

toudi commented 1 year ago

dzięki za miłe słowa :) rozważam jeszcze dodanie wsparcia dla importu faktur z yaml i/lub JSON - myślisz, że ma to sens? aktualnie wspierane jest CSV oraz w bardzo niedalekiej przyszłości chcę dodać wsparcie dla plików excela .xlsx (podobnie zrobiłem w JPK_VAT) co do keyctl to po prostu myślę, że sforkuję paczkę której używam do obsługi keyringów i dodam tam wsparcie dla keyctl oraz zrobię pull requesta żeby wrzucić zmiany do oryginalnej paczki

kuncy7 commented 1 year ago

Ja bym poczekał z tym dodawaniem wsparcia, nie do końca wiadomo co władza wymyśli. Program ze wsparciem keyctl na pewno sprawdzę i przetestuję.

toudi commented 1 year ago

ok przeszukałem internet ponownie i okazuje się, że keyctl owszem umożliwia przechowywanie kluczy tylko że one są ulotne. oznacza to, że oczywiście mogę dodać wsparcie dla tego typu keyringu tyle tylko, że to będzie kontrskuteczne bo po kolejnym reboocie klucz zniknie Ci z sesji i musiałbyś wygenerować nowy w aplikacji KSeF (a to z kolei jest bez sensu bo klucza używasz tylko podczas operacji upload - czyli raz) To co potrafię sobie wyobrazić to:

kuncy7 commented 1 year ago

Szkoda że `keyctl' traci "pamięć" po reboocie. Kombinuje jak załadować token na poziomie startu systemu. To o tyle dobra opcja że działoby się z poziomu root'a . Ta druga opcja wydaje się chyba najbardziej sensowna, chyba podobnie tu jest zrobione: https://github.com/alapierre/go-ksef-cli . Pierwsza (z parametrem) też dobra, jakoś sam "zabezpieczę" token (w bazie np.) .

toudi commented 1 year ago

sporzałem na tamten kod źródłowy i tam jest to tak wykombinowane, że w keyringu trzymany jest klucz szyfrowania aes który z kolei używany jest do szyfrowania plku na dysku. co oznacza, że i tak jesteśmy w punkcie zero bo kolega alapierre używa dokładnie tej samej paczki do keyringu co ja :) innymi słowy nawet żeby wydobyć klucz aes z keyringu to .. najpierw trzeba się do keyringu dobić a to właśnie jest kwintesencją tego buga.

zbliża się weekend więc postaram się postawić czystą wirtualkę z ubuntu i zobaczyć czy uda mi się zainstalować (jesteś w stanie mi podać nieco więcej szczegółów n/t systemu? czy wystarczy mi po prostu ubuntu 22.04 w trybie headless?)

kuncy7 commented 1 year ago
  • dodanie parametru do komendy upload w którym podajesz token i/lub nazwy zmiennej środowiskowej - dzięki temu będziesz mógł go sobie zapisać w innym miejscu (np. na komputerze hosta w keepassx)

W obecnej sytuacji, chyba takie rozwiązanie byłoby dla mnie najlepsze. Token zaszyfrował bym w gpg i całość oskryptował. Proszę o dodanie jakiegoś parametru umożliwiającego przekazanie tokena wprost do programu.

toudi commented 1 year ago

co byś powiedział na coś takiego?

./ksef upload --help
Usage of upload:
  -i    użyj sesji interaktywnej
  -p string
        ścieżka do katalogu z wygenerowanymi fakturami
  -sj
        użyj formatu JSON do zapisu pliku statusu (domyślnie YAML)
  -t    użyj bramki testowej
  -token string
        Token sesji interaktywnej lub nazwa zmiennej środowiskowej która go zawiera

toudi@x300:~/projects/ksef-go> more token.plaintext
12345
toudi@x300:~/projects/ksef-go> gpg -c token.plaintext
toudi@x300:~/projects/ksef-go> hexdump -C token.plaintext.gpg 
00000000  8c 0d 04 09 03 08 2d 40  22 6e b6 65 c0 90 ff d2  |......-@"n.e....|
00000010  4a 01 91 00 f3 52 53 04  1c e5 49 44 1d ab 6c dc  |J....RS...ID..l.|
00000020  db a2 09 5b 49 44 53 47  27 f8 83 d0 da 10 eb 67  |...[IDSG'......g|
00000030  58 88 e8 1e 49 fc bc 29  d0 84 8f fc 7e c3 37 8e  |X...I..)....~.7.|
00000040  47 87 c4 f8 c4 66 79 39  ea 3b c0 bd ff 3e ac 89  |G....fy9.;...>..|
00000050  d1 7d cb 79 20 02 e2 21  c4 ee 5b                 |.}.y ..!..[|
0000005b
toudi@x300:~/projects/ksef-go> TOKEN=`gpg -d token.plaintext.gpg` ./ksef upload -t -i -p przyklady -token TOKEN

w wyniku takiego wywołania, program: 1/ spróbuje odczytać zmienną środowiskową TOKEN 2/ jeśli powyższa będzie pusta, potraktuje frazę TOKEN jako treść tokenu 3/ jeśli pomimo tego token dalej będzie pusty, spróbuje odczytać go z keyringu

// edit: po prostu pomyślałem sobie, że nawet gdyby komenda zapisała się w historii shella to i tak nie wyciekłaby wartość samego tokenu a jedynie nazwa tymczasowej zmiennej środowiskowej ale jeśli będziesz chciał to oczywiście można podać token jak leci, plaintextem

toudi commented 1 year ago

dodałem release 0.1.5. testuję paczkę do automatycznego wydawania binarek żeby nie robić tego z łapy za każdym razem :)

kuncy7 commented 1 year ago

Super, dzięki, będę testował, dam znać. Tylko taka techniczna uwaga, jakoś przy tym automatycznym budowaniu, binarki się rozmnożyły x2. Po 2 są dla linuxa i po 2 dla mac os, no chyba że tak ma być.

toudi commented 1 year ago

no wiesz, teoretycznie binarkę arm64 dla linuksa możesz wrzucić np na raspberry PI. tak samo formalnie rzecz biorąc apple wciąż supportuje maki które mają procesory intela - arm64-darwin jest dla chipsetu m1 (apple silicon). Aczkolwiek ta paczka której używam teraz nie do końca mi pasuje, chcę przetestować jeszcze jedną (go-releaser czy jakoś tak) bo ona wtedy do release'u dołącza od razu changeloga)

w każdym razie, cytując klasyka:

będzie pan zadowolony

:D

kuncy7 commented 1 year ago

Gapiłem się na listę chyba 5 minut i nie zauważyłem różnicy pomiędzy arm i amd . Trzeba będzie nowe okulary kupić! :)

kuncy7 commented 1 year ago

Pierwsza próba użycia:

ksef upload -t -i -p przyklady -token E64D1E1xxxxxxxxxxxxxxxxx
error running upload:  
cannot login to gateway: unexpected response code: 400 != 2xx or err: <nil>

Katalog przyklady jest zawiera 2 faktury, katalog klucze też jest z certyfikatami. Token "stary" i "nowy" teraz wygenerowany, taki sam komunikat. Da się jakiś debug włączyć??

[Edit] Pewnie brakuje NIP, jest token, a nie wysyła się NIP, jak w przykładzie z ksef save-token

toudi commented 1 year ago

NIP jest odczytywany z plików xml faktur automatycznie i musi oczywiście być zgodny z numerem NIP na jaki się logujesz i otrzymujesz token. Przykładowo:

  <Podmiot1>
    <DaneIdentyfikacyjne>
      <NIP>1112223344</NIP>
      <Nazwa>Moja firma ABC</Nazwa>

w komendzie save-token numer NIP podaje się tylko dlatego, żeby później komenda upload już o niego nie pytała tylko mogła automatycznie wyciągnąć sobie token z keyringu na podstawie NIPu z faktur.

dodałem eksperymentalny release (0.1.6-debug) który zaraz skasuję bo chcę debugowanie zrobić o wiele lepiej - teraz loguję najbardziej newralgiczne rzeczy na stdout.

próbowałem podawać token zarówno przez zmienną środowiskową jak i bezpośrednio i śmiga

kuncy7 commented 1 year ago

Uzgodniłem NIPy i mam tak:

ksef upload -t -i -p przyklady -token E71A51F77ECA087CC8BC21BB8E0D62B5Exxxxxxxxxxxx

response body: 
{"exception":{"serviceCtx":"default","serviceCode":"20231121-EX-9462A54420-F64DB6C364-8B","serviceName":"online.session.session.token.init","timestamp":"2023-11-21T16:22:36.849Z","referenceNumber":"20231121-SE-B7E47D97D8-0F65B43198-AD","exceptionDetailList":[{"exceptionCode":21401,"exceptionDescription":"Dokument nie jest zgodny ze schemą (xsd)."}]}}
error running upload:
cannot login to gateway: unexpected response code: 400 != 2xx or err: <nil>

Jak trzeba wkleję cały log z sesji. Faktura wczytuje się poprawnie przez stronę [Edit] Cały log z sesji, token w komendzie, nip to 8888888888

ksef upload -t -i -p przyklady -token 43BF872C1A3E7DFF92CE8784329437227DFBFBF42C9DB77EF39153EA0A30C011
challengePlaintext: 43BF872C1A3E7DFF92CE8784329437227DFBFBF42C9DB77EF39153EA0A30C011|-62135596800000
posting xml template: 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<auth:InitSessionTokenRequest
    xmlns="http://ksef.mf.gov.pl/schema/gtw/svc/online/types/2021/10/01/0001"
    xmlns:types="http://ksef.mf.gov.pl/schema/gtw/svc/types/2021/10/01/0001"
    xmlns:auth="http://ksef.mf.gov.pl/schema/gtw/svc/online/auth/request/2021/10/01/0001">
    <auth:Context>
        <Challenge></Challenge>
        <Identifier xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:type="types:SubjectIdentifierByCompanyType">
            <types:Identifier></types:Identifier>
        </Identifier>
        <DocumentType>
            <types:Service>KSeF</types:Service>
            <types:FormCode>
                <types:SystemCode>FA (2)</types:SystemCode>
                <types:SchemaVersion>1-0E</types:SchemaVersion>
                <types:TargetNamespace>http://crd.gov.pl/wzor/2023/06/29/12648/</types:TargetNamespace>
                <types:Value>FA</types:Value>
            </types:FormCode>
        </DocumentType>
        <Encryption>
            <types:EncryptionKey>
                <types:Encoding>Base64</types:Encoding>
                <types:Algorithm>AES</types:Algorithm>
                <types:Size>256</types:Size>
                <types:Value>W+pZzO6dKp+8QIbrvNFtGpXKFa/dr3tf92v9dN0CzbgFvSuCp8ubULNpU6mOjIFHBDhJA9nsNg1LtiKtY0DcTtC+qjov14U5T9fbUE/TLzmZi6/ctQtUMhRita8yifG7QKS+Ru6RywOO3XN4Mf1L15S+gBzRS+uAnY1lOGCrs/A94wcYNgxhkBEbfVm9txFDdGbucDsQsdfixBvuGyfhlW9Z5eqJKcA3M2zehZ4bBAQmAEw5r9haikII2oRoiaBx5l+NAeiobKfrBPI3zKWLTZPse5AdrkrQPui8zMrdD7zhtoK5qeIfE2SvxFClqOUuCQC7BPXqhm++zeuGyhaCEA==</types:Value>
            </types:EncryptionKey>
            <types:EncryptionInitializationVector>
                <types:Encoding>Base64</types:Encoding>
                <types:Bytes>16</types:Bytes>
                <types:Value>BQZQJbmbKnEnn+suByb8Fg==</types:Value>
            </types:EncryptionInitializationVector>
            <types:EncryptionAlgorithmKey>
                <types:Algorithm>RSA</types:Algorithm>
                <types:Mode>ECB</types:Mode>
                <types:Padding>PKCS#1</types:Padding>
            </types:EncryptionAlgorithmKey>
            <types:EncryptionAlgorithmData>
                <types:Algorithm>AES</types:Algorithm>
                <types:Mode>CBC</types:Mode>
                <types:Padding>PKCS#7</types:Padding>
            </types:EncryptionAlgorithmData>
        </Encryption>
        <Token>YbytBXO1HLrzrVtato316JCdc5OWAvleQKiq26SxuXzobVn+dkBtrpmXObnPUuO50UcCXoI4Td/a7TpfDSlR0GxKLQnyedGjAVpSCzWM86TugcEp4KjVDm3BK9R7iTtYnYdS+135qvS0IObUZhB5HpnoR50N6u1A49oEItKgInKIJ/lO8+f2klKUvRqA41qJ4YRu+0RjIuYLdLzD9UWoXb5XQVMp4WjkJiLKeAIvcUlNAzZ3iCQkx6L5i0du/s9JlzvzCXQbrbLoUaqul0ZGyGh6qnecSHfQPSwOwS6ILqIRmV8+xq2dXEl2c0q8y3Mxa9Ivad7l27nh45x0Yxg1Ew==</Token>
    </auth:Context>
</auth:InitSessionTokenRequest>
response body: 
{"exception":{"serviceCtx":"default","serviceCode":"20231121-EX-69430B62B3-5383B88DBF-2E","serviceName":"online.session.session.token.init","timestamp":"2023-11-21T16:41:59.405Z","referenceNumber":"20231121-SE-BDD28D66E6-F28A1FB24F-D5","exceptionDetailList":[{"exceptionCode":21401,"exceptionDescription":"Dokument nie jest zgodny ze schemą (xsd)."}]}}
error running upload:
cannot login to gateway: unexpected response code: 400 != 2xx or err: <nil>
toudi commented 1 year ago

widzę trzy bardzo dziwne rzeczy:

co sugeruje mi, że błąd jest gdzieś wcześniej. pododaję dodatkowe debugi i zrobię nowy build i zobaczymy w czym tkwi problem.

toudi commented 1 year ago

udało mi się zreplikować Twój błąd ale jedynie wtedy kiedy zrobiłem literówkę i wywołałem program na katalogu przyklad a nie przyklady. (czyli na katalogu który zawiera źródłowe csv a nie wynikowe xml'e) W każdym razie dodałem nieco więcej debuga oraz dodatkowo dodałem warunek, że jeśli program nie sparsuje żadnego NIPu to zwraca błąd. cały czas pracuję nad lepszym trybem diagnostycznym ale to mi chwilę zajmie. możesz to zobaczyć w wersji 0.1.7-debug

kuncy7 commented 1 year ago

W wersji 0.1.7-debug jest tak:

./ksef upload -t -i -p przyklady -token 43BF872C1A3E7DFF92CE8784329437227DFBFBF42C9DB77EF39153EA0A30C011
error running upload:
cannot parse invoice collection: no issuer found - this should be impossible

W katalogu przyklady mam fakturę w xmlu z takim nagłówkiem:

 <Podmiot1>
    <DaneIdentyfikacyjne>
      <NIP>8888888888</NIP>
      <Nazwa>CHEMIA SP. Z O.O.</Nazwa>
    </DaneIdentyfikacyjne>
    <Adres>
      <KodKraju>PL</KodKraju>
      <AdresL1>Aleje Krymskie 4</AdresL1>
      <AdresL2>88-888 Piaseczno</AdresL2>
    </Adres>
    <DaneKontaktowe>
      <Telefon>+48-22-2222222</Telefon>
    </DaneKontaktowe>
  </Podmiot1>
toudi commented 1 year ago

czy jest możliwość, że tych faktur nie wygenerowałeś moim programem i że nie zaczynają (tzn pliki z fakturami) prefiksem invoice- ? w sumie tak jak teraz na to patrzę to faktycznie idiotyczne to było założenie i chyba to zmienię. chodziło mi o to żeby móc w programie w jakiś szybki sposób zrobić detekcję czy plik jest plikiem faktury czy jest to np. UPO

// edit. chodzi mi o to, że u mnie pliki po etapie generacji wyglądają w ten sposób:

drwxr-xr-x 1 toudi toudi  234 11-11 04:51 .
drwxr-xr-x 1 toudi toudi  628 11-21 20:36 ..
-rw-r--r-- 1 toudi toudi 2,0K 11-21 20:31 invoice-0.xml
-rw-r--r-- 1 toudi toudi 2,0K 11-21 20:31 invoice-1.xml
-rw-r--r-- 1 toudi toudi   58 11-21 20:31 status.yaml
kuncy7 commented 1 year ago

Tak, to są faktury wygenerowane bezpośrednio przez program (do fakturowania) i nazywają się np. SP_FV_004_10_2023.xml

toudi commented 1 year ago

dobra to już w takim razie wszystko jasne. zmienię warunek detekcji i dam znać

toudi commented 1 year ago

zobacz proszę wersję 0.1.8-debug

kuncy7 commented 1 year ago

Zadziałało, wysłałem i obrałem upo! :)

toudi commented 1 year ago

super :D to ja popracuję teraz nad lepszym trybem diagnostycznym i mimo wszystko przetestuję podlinkowanego alternatywnego demona do trzymania keyringu. kombinuję też porządną dokumentację użytkownika

kuncy7 commented 1 year ago

Taki demon się przyda, ale opcji -token nie usuwaj, może się przydać np. dla takich co chcą trzymać token w bazie. Dokumentację też warto poprawić, choć i ta jest niezla.

Fajnie że jest ten klient, dzięki! Czekam na finalną wersję.

[Edit] W sumie teraz sobie zdałem sprawę że brakuje jednej funkcjonalności: pobierania faktur . Jakieś plany związane z pobieraniem faktur są?