2023-11-05
Chcesz skonfigurować drukarkę, żeby automatycznie wysyłała faksy? A może chcesz codziennie dostać na maila raport o ilości wolnego dysku na domowym serwerze? A może po prostu chcesz z poziomu programu, czy skryptu wysłać sobie maila? W takim przypadku musisz skonfigurować, drukarkę, czy skrypt do korzystania z serwera SMTP. Jest jednak drobny problem. Ileś tam lat temu, żeby wysłać maila wystarczyło znać nazwę użytkownika i hasło i było to mocno wykorzystywane przez spamerów. Dlatego konfiguracja SMTP jest chyba obecnie jedną z najcięższych dla administratora, a i dla programisty wiele się zmieniło. Jeśli chcesz użyć SMTP programistycznie musisz wygenerować sobie odpowiedni token, tzw. application password. Tutaj pokażę, jak to zrobić z kontem GMAIL.
- Udaj się na https://security.google.com/settings/security/apppasswords. Jest to strona, która pozwala zdefiniować app passwords. Jednym z utrudnień dla spamerów ma być to, że wszelkie automaty używające Twojego konta pocztowego powinny mieć swoje hasła, nie mogą one korzystać z hasła, jakim zabezpieczasz całe swoje konto.
- Wymyśl jakąć nazwę aplikacji, np. „Drukarka Xerox” albo „Mój skrypt XYZ”. Po kliknięciu Create zostanie wyświetlone hasło.
Uwaga: hasłem są poszczególne literki/cyferki, spacje między nimi już nie.
- Teraz przejdź do konfiguracji poczty wychodzącej Twojej drukarki, albo skryptu. Np. ustawienia na mojej drukarce są takie:
a tak wygląda konfiguracja connectora email na Azure:
a tak wygląda skrypt w pythonie:
import smtplib
mailFrom = 'Your automation system'
mailTo = ['XXX@wp.pl','YYY@gmail.com']
mailSubject = 'Processing finished successfully'
mailBody = '''Hello
This mail confirms that processing has finished without problems,
Have a nice day!'''
message = '''From: {}
Subject: {}
{}
'''.format(mailFrom, mailSubject, mailBody)
user = 'my_user@gmail.com'
password = '***********'
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(user,password)
server.sendmail(user, mailTo, message)
server.close()
print('mail sent')
2023-11-05
W Azure mamy dwa rodzaje logic apps: consumption i standard. Z zewnątrz oba wyglądają podobnie, bo i nazwa taka sama i sposób budowy aplikacji podobny, więc w czym problem?
Otóż okazuje sie, że wewnętrzenie te dwa modele logic app to coś zupełnie innego. O ile consumption to rzeczywiście usługa serverless, już wstępnie skonfigurowana i z tonami dokumentacji, o tyle standard jest właściwie aplikacją webową z przydzielonymi zasobami compute i wymaga dodatkowej konfiguracji niemal na każdym kroku, tymczasem z dokumentacją jest…. tak jakby nieco gorzej.
Jeden z problemów polega na tym, że logic app standard workflow stateless nie posiada historii! Nie widać kiedy się uruchomił workflow i co robił, kiedy już się go udało uruchomić.
Jest na to rozwiązanie wskazane o tutaj: https://learn.microsoft.com/en-us/azure/logic-apps/create-single-tenant-workflows-azure-portal#enable-run-history-for-stateless-workflows
W settings >> configuration należy samodzielnie dodać nowe ustawienie o nazwie:
Workflows.<nazwa_workflow>.OperationOptions
a w jej wartości wprowadzić tekst:
WithStatelessRunHistory
Zapisanie zmian spowoduje restart aplikacji, ale co tam – dzięki temu będzie widać co się działo z aplikacją!
2023-11-05
Debugowanie aplikacji, czy skryptu z wykorzystaniem lokalnie instalowanych narzędzi to … przyjemność. Co jednak zrobić jeśli zdebugować trzeba nieco dziwne Logic Apps?
Oto propozycja.
- Zacznij od przejścia na stronę https://webhook.site/
Spowoduje to otwarcie strony oczekującej na tzw. webhook, czyli skierowane do tej strony żądanie POST. Teraz trzeba skonstruować to żądanie POST
- W swojej aplikacji, w workflow dodaj nowy krok – akcję HTTP. Formatkę wypełnij w następujący sposób:
- Metoda – POST
- URI – wklej adres strony uzyskany w kroku nr 1
- Body – skonstuuj jakiekolwiek tylko wyrażenie chcesz śledzić. Generalnie, to co tutaj napiszesz, za chwilę będziesz mógł zobaczyć na stronce z kroku nr 1
- Zapisz zmiany i uruchom swoją aplikację. Kiedy workflow przejdzie do kroku z pkt. 2, to wywoła wskazany adres przekazując body zbudowane z aktualnej wartości zmiennych. Dzięki temu możesz zobaczyć, co tam się dzieje w środku aplikacji!
2023-10-21
Funkcje, czyli z grubsza rzecz biorąc, główni reprezentanci linii serverless w Azure (FunctionApp i LogicApp) mogą łączyć się z siecią w trzech płaszczyznach:
- przez adres publiczny – jeśli aplikacja jest udostępniona publicznie
- przez private endpoint – co jest wykorzystywane do połączenia się do funkcji (klient chce skorzystać z funkcjonalności funkcji, więc łączy się do jej endpointa
- przez integration subnet – ten rodzaj połączenia jest wykorzystywany przez funkcję, kiedy chce ona „wyjść na zewnątrz”, np. w celu skorzystania z innych zasobów, które są potrzebne do działania tej funkcji.
Integration subnet nigdy nie jest wykorzystywane do połączenia się do funkcji. Nawet jeśli do integration subnet podłączysz NSG z regułami inbound, to zostaną one zignorowane, bo ruch przychodzący po prostu nie działa. Jedynym wyjątkiem są pakiety transferowane w ramach odpowiedzi na komunikację wychodzącą z funkcji, ale to zrozumiałe, bo bez tego komunikacja nie miałaby sensu.
Dzięki sprytnemu połączeniu ręcznie konfigurowanego routingu, NSG, integracji z Firewallem i innych mechanizmów konfiguracji sieci, administrator ma szeroki zakres możliwości definiowania jakie połączenia mogą być nawiązywane przez funkcje, np.: korzystanie z zasobów lokalnych sieci, połączenie do on-prem, połączenia z express route, innymi endpointami, wyjście do Internetu itd.
Do wykonania konfiguracji NSG może się przydać znajomość prywatnego adresu IP funkcji w integration subnet. Jest on zapisany w zmiennej środowiskowej WEBSITE_PRIVATE_IP.
Ruch sieciowy generowany przez funkcję podlega normalnym regułom. Jeśli np. chcesz przesłać pakiety do gateway’a, wystarczy odpowiednio zmodyfikować trasy routingu przypisane do podsieci.
Co ciekawe, application plan bazujący na windows, może się integrować z dwiema podsieciami, a na linux, tylko z jedną.
Sam routing to również ciekawa sprawa, bo można go konfigurować w trzech zakresach:
- Routing aplikacyjny – określa, co ma sie stać z ruchem generowanym przez działającą aplikację. Może sięgać tylko do zasobów lokalnych, albo wychodzić na zewnątrz
- Routing konfiguracyjny – określa, jak należy wykonywać routing przed uruchomieniem aplikacji, co jest wymagane np. do wykonania operacji pull image for container. Domyślnie komunikacja jest wykonywana przez połączenie publiczne, jeśli ma być inaczej, to wymagana jest zmiana. Jeśli funkcja ma sięgać do Key Vault po zapisane tam sekrety, które mają być np. używane w konfiguracji funkcji, to jeśli taka publiczna komunikacja jest zablokowana, to funkcja podejmuje próbę połączenia przez integration subnet
- Routing sieciowy – pozwala na zdefiniowanie konkretnych tras. Generalnie, ruch wychodzący z funkcji podlega wszystkim normalnym zasadom routingu, które przynajmniej częściowo można tutaj zdefiniować.
Z drugiej strony private endpoint, pozwala na połączenie się do usługi. Endpoint jest podłączony do wybranej podsieci, otrzymuje swój adres IP, a ten adres powinien być zarejestrowany w DNS. Dzięki temu wybrane usługi będą mogły połączyć się do funkcji i skorzystać z jej funkcjonalności.
Integrate your app with an Azure virtual network – Azure App Service | Microsoft Learn
2023-10-12
Opss. terraform się wywalił i w efekcie, część zasobów została utworzona w Azure, ale plik stanu nie został zaktualizowany. W takim przypadku otrzymsz błąd:
Error: A resource with the ID „/subscriptions/XXXX/resourceGroups/RG-TerraformLab/providers/Microsoft.Network/virtualNetworks/KRK-VNET/subnets/dev_subnet” already exists – to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for „azurerm_subnet_network_security_group_association” for more information.
No tak, to problemy mam dwa: 1 – zaimportowanie obiektu tworzonego przez for_each i 2 – próbuję utworzyć zasób azurerm_subnet_network_security_group_association, tymczasem brakujący obiekt to po prostu azurerm_subnet.
Na szczęście komunikat o błędzie zawiera już prawie wszystko, co trzeba. Rzeczywiście polecenie import oczekuje dwóch parameterów. Nazwy zasobu tak jak jest ona zdefiniowana dla Azure oraz identyfikatora zasobu. Na dodatek, to właśnie obiekt subnet zawiera w sobie informacje o association, więc w sumie, to problemu nie ma. No to jedziemy:
terraform import azurerm_subnet_network_security_group_association.sub_nsg["dev_subnet"] /subscriptions/XXXX/resourceGroups/RG-TerraformLab/providers/Microsoft.Network/virtualNetworks/KRK-VNET/subnets/dev_subnet
Niestety – komenda u mnie nie działa dobrze:
Index brackets must contain either a literal number or a literal string.
No jak to!? Przecież mam „literal string”. O co chodzi? Chodzi o to, że jestem fanem powershella i pracuję w powershellu. Tutaj poprawna komenda to:
terraform import azurerm_subnet_network_security_group_association.sub_nsg[\`"dev_subnet\`"] /subscriptions/XXXX/resourceGroups/RG-TerraformLab/providers/Microsoft.Network/virtualNetworks/KRK-VNET/subnets/dev_subnet
Uff – udało się!
2023-10-04
Świeżo utworzona maszyna w Azure, z Windows na pokładzie. Błąd przy logowaniu:
An authentication error has occurred. The credentials supplied to the package were not recognized
No cóż… pamięć już nie taka, ale przecież hasło wprowadzam dobre! Okazuje się, że nazwę logowania podawałem po prostu w postaci <username>. W takim przypadku Azure czasami trochę wariuje i nie wie, w jakim kontekście zinterpretować nazwę użytkownika.
Zmień nazwę na:
AzureAD\username – jeśli to logowanie ma się wykonać w kontekście użytkownika Azure AD
lub
.\username – jeśli to logowanie na zwykłego użytkownika
I już!
2023-09-12
Zdarza się, że chcesz stworzyć kopię repozytorium, która ma zacząć żyć swoim własnym życiem. W takim przypadku:
1 – Sklonuj repozytorium na swój komputer:
git clone --bare https://github.com/my-user/old-repo.git
2 – Przejdź do katalogu ze skolonowanym repozytorium i wyślij je do nowego repozytorium:
cd old-repo.git
git push --mirror https://github.com/EXAMPLE-USER/NEW-REPOSITORY.git
3 – Repozytorium jest już na miejscu! Jeśli chcesz, to usuń kopię z lokalnego komputera
Jeśli oryginalne repozytorium jest duże (zawiera np. również pliki binarne to posłuż się metodą opisaną tutaj:
https://docs.github.com/en/repositories/creating-and-managing-repositories/duplicating-a-repository#mirroring-a-repository-that-contains-git-large-file-storage-objects