libzypp: zypp/ng/workflows/repoinfowf.cc Source File

libzypp 17.36.6

repoinfowf.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include "repoinfowf.h"
10#include "zypp/ng/reporthelper.h"
11#include <zypp/ng/workflows/contextfacade.h>
12#include <zypp-core/ManagedFile.h>
13#include <zypp-core/base/String.h>
14#include <zypp-core/base/Gettext.h>
15#include <zypp-core/fs/TmpPath.h>
16#include <zypp/base/StrMatcher.h>
17#include <zypp/KeyRing.h>
18#include <zypp-common/PublicKey.h>
19#include <zypp/ZYppCallbacks.h>
20
21#include <utility>
22#include <zypp-core/zyppng/pipelines/Transform>
23#include <zypp-core/zyppng/pipelines/Expected>
24#include <zypp-core/zyppng/pipelines/MTry>
25#include <zypp-media/ng/Provide>
26#include <zypp-media/ng/ProvideSpec>
27#include <zypp/MediaSetAccess.h>
28#include <zypp/ng/Context>
29#include <zypp/ng/UserRequest>
30#include <zypp/ng/workflows/logichelpers.h>
31
32#include <fstream>
33
34
35namespace zyppng {
36
37 namespace {
38
39 using namespace zyppng::operators;
40
41 template<class Executor, class OpType>
42 struct RepoInfoProvideKeyLogic : public LogicBase<Executor, OpType> {
43
44 using ZyppContextRefType = MaybeAsyncContextRef<OpType>;
45 using ZyppContextType = remove_smart_ptr_t<ZyppContextRefType>;
46 using ProvideType = typename ZyppContextType::ProvideType;
47 using MediaHandle = typename ProvideType::MediaHandle;
48 using ProvideRes = typename ProvideType::Res;
49
50 RepoInfoProvideKeyLogic( ZyppContextRefType &&zyppContext, zypp::RepoInfo &&info, std::string &&keyID_r, zypp::Pathname &&targetDirectory_r )
51 : _reports( std::move(zyppContext ))
52 , _info( std::move(info) )
53 , _keyID_r(std::move( keyID_r ))
54 , _targetDirectory_r(std::move( targetDirectory_r ))
55 , _keyIDStr( _keyID_r.size() > 8 ? _keyID_r.substr( _keyID_r.size()-8 ) : _keyID_r ) // print short ID in Jobreports
56 , _tempKeyRing( _tmpKeyRingDir )
57 { }
58
59 ZYPP_ENABLE_LOGIC_BASE( Executor, OpType );
60
61 MaybeAsyncRef<zypp::filesystem::Pathname> execute () {
62 using namespace zyppng::operators;
63 using zyppng::operators::operator|;
64 using zyppng::expected;
65
66
67 if ( _keyID_r.empty() )
68 return makeReadyResult(zypp::Pathname{});
69
70 importKeysInTargetDir();
71
72 if ( _tempKeyRing.isKeyTrusted( _keyID_r) ) {
73 return makeReadyResult(writeKeysToTargetDir());
74 }
75
76 if ( _info.gpgKeyUrlsEmpty() ) {
77 // translator: %1% is a repositories name
78 _reports.info( zypp::str::Format(_("Repository %1% does not define additional 'gpgkey=' URLs.") ) % _info.asUserString() );
79 return makeReadyResult(writeKeysToTargetDir());
80 }
81
82 // no key in the cache is what we are looking for, lets download
83 // all keys specified in gpgkey= entries
84
85 // translator: %1% is a gpg key ID like 3DBDC284
86 // %2% is a repositories name
87 _reports.info( zypp::str::Format(_("Looking for gpg key ID %1% in repository %2%.") ) % _keyIDStr % _info.asUserString() );
88
89 return _info.gpgKeyUrls()
90 | transform( [this]( const zypp::Url &url ) {
91
92 _reports.info( " gpgkey=" + url.asString() );
93 return fetchKey( url )
94 | and_then( [this, url]( zypp::ManagedFile f ) -> expected<void> {
95 try {
96 if ( f->empty() )
97 return expected<void>::error(std::make_exception_ptr( zypp::Exception("Empty ManagedFile returned.") ));
98
99 zypp::PublicKey key(f);
100 if ( !key.isValid() )
101 return expected<void>::error(std::make_exception_ptr( zypp::Exception("Invalid public key.") ));
102
103 // import all keys into our temporary keyring
104 _tempKeyRing.multiKeyImport(f, true);
105
106 } catch ( const std::exception & e ) {
107 //ignore and continue to next url
108 ZYPP_CAUGHT(e);
109 MIL << "Key import from url:'"<<url<<"' failed." << std::endl;
110 return expected<void>::error( ZYPP_FWD_CURRENT_EXCPT() );
111 }
112
113 return expected<void>::success();
114 });
115
116 })
117 | [this]( std::list<expected<void>> && ) ->zypp::Pathname {
118 return writeKeysToTargetDir();
119 };
120 }
121
122 protected:
123
124 MaybeAsyncRef<zyppng::expected<zypp::ManagedFile>> fetchKey ( const zypp::Url &url ) {
125 return _reports.zyppContext()->provider ()->provide( url, zyppng::ProvideFileSpec() )
126 | and_then( ProvideType::copyResultToDest( _reports.zyppContext()->provider(), _targetDirectory_r / zypp::Pathname( url.getPathName() ).basename() ) );
127 }
128
129 void importKeysInTargetDir () {
130 MIL << "Check for " << _keyID_r << " at " << _targetDirectory_r << std::endl;
131
132 // translator: %1% is a gpg key ID like 3DBDC284
133 // %2% is a cache directories path
134 _reports.info( zypp::str::Format(_("Looking for gpg key ID %1% in cache %2%.") ) % _keyIDStr % _targetDirectory_r );
135 zypp::filesystem::dirForEach( _targetDirectory_r,
136 zypp::StrMatcher(".key", zypp::Match::STRINGEND),
137 [this]( const zypp::Pathname & dir_r, const std::string & str_r ){
138 try {
139
140 // deprecate a month old keys
141 zypp::PathInfo fileInfo ( dir_r/str_r );
142 if ( zypp::Date::now() - fileInfo.mtime() > zypp::Date::month ) {
143 //if unlink fails, the file will be overriden in the next step, no need
144 //to show a error
145 zypp::filesystem::unlink( dir_r/str_r );
146 } else {
147 _tempKeyRing.multiKeyImport(dir_r/str_r, true);
148 }
149 } catch (const zypp::KeyRingException& e) {
150 ZYPP_CAUGHT(e);
151 ERR << "Error importing cached key from file '"<<dir_r/str_r<<"'."<<std::endl;
152 }
153 return true;
154 });
155 }
156
157 zypp::Pathname writeKeysToTargetDir() {
158
159 zypp::filesystem::assert_dir( _targetDirectory_r );
160
161 //now write all keys into their own files in cache, override existing ones to always have
162 //up to date key data
163 for ( const auto & key: _tempKeyRing.trustedPublicKeyData()) {
164 MIL << "KEY ID in KEYRING: " << key.id() << std::endl;
165
166 zypp::Pathname keyFile = _targetDirectory_r/(zypp::str::Format("%1%.key") % key.rpmName()).asString();
167
168 std::ofstream fout( keyFile.c_str(), std::ios_base::out | std::ios_base::trunc );
169
170 if (!fout)
171 ZYPP_THROW(zypp::Exception(zypp::str::form("Cannot open file %s",keyFile.c_str())));
172
173 _tempKeyRing.dumpTrustedPublicKey( key.id(), fout );
174 }
175
176 // key is STILL not known, we give up
177 if ( !_tempKeyRing.isKeyTrusted( _keyID_r) ) {
178 return zypp::Pathname();
179 }
180
181 zypp::PublicKeyData keyData( _tempKeyRing.trustedPublicKeyData( _keyID_r ) );
182 if ( !keyData ) {
183 ERR << "Error when exporting key from temporary keychain." << std::endl;
184 return zypp::Pathname();
185 }
186
187 return _targetDirectory_r/(zypp::str::Format("%1%.key") % keyData.rpmName()).asString();
188 }
189
190 JobReportHelper<ZyppContextRefType> _reports;
191 const zypp::RepoInfo _info;
192 const std::string _keyID_r;
193 const zypp::Pathname _targetDirectory_r;
194 const std::string _keyIDStr;
195
196 zypp::filesystem::TmpDir _tmpKeyRingDir;
197 zypp::KeyRing _tempKeyRing;
198 };
199
200
201 struct AsyncRepoInfoProvideKey : public RepoInfoProvideKeyLogic<AsyncRepoInfoProvideKey, zyppng::AsyncOp<zypp::Pathname>>
202 {
203 using RepoInfoProvideKeyLogic::RepoInfoProvideKeyLogic;
204 };
205
206 struct SyncRepoInfoProvideKey : public RepoInfoProvideKeyLogic<SyncRepoInfoProvideKey, zyppng::SyncOp<zypp::Pathname>>
207 {
208 using RepoInfoProvideKeyLogic::RepoInfoProvideKeyLogic;
209 };
210 }
211
212 zypp::filesystem::Pathname RepoInfoWorkflow::provideKey( SyncContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::filesystem::Pathname targetDirectory_r )
213 {
214 return SimpleExecutor<RepoInfoProvideKeyLogic, SyncOp<zypp::filesystem::Pathname>>::run( std::move(ctx), std::move(info), std::move(keyID_r), std::move(targetDirectory_r) );
215 }
216
217 AsyncOpRef<zypp::filesystem::Pathname> RepoInfoWorkflow::provideKey(ContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::filesystem::Pathname targetDirectory_r )
218 {
219 return SimpleExecutor<RepoInfoProvideKeyLogic, AsyncOp<zypp::filesystem::Pathname>>::run( std::move(ctx), std::move(info), std::move(keyID_r), std::move(targetDirectory_r) );
220 }
221
222}
KeyRing.h
MediaSetAccess.h
StrMatcher.h
ZYppCallbacks.h
zypp::Date::month
static const ValueType month
Definition Date.h:49
zypp::Date::now
static Date now()
Return the current time.
Definition Date.h:78
zypp::Match::STRINGEND
@ STRINGEND
Match at string end.
Definition StrMatcher.h:45
zypp::RepoInfo
What is known about a repository.
Definition RepoInfo.h:72
zypp::Url::asString
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:515
zypp::Url::getPathName
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition Url.cc:622
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:47
zypp::filesystem::Pathname::c_str
const char * c_str() const
String representation.
Definition Pathname.h:112
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition Pathname.h:116
zyppng::expected::success
static expected success(ConsParams &&...params)
Definition expected.h:115
zyppng::expected::error
E & error()
Definition expected.h:225
contextfacade.h
logichelpers.h
ZYPP_ENABLE_LOGIC_BASE
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
Definition logichelpers.h:223
zypp::filesystem::unlink
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
zypp::filesystem::dirForEach
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
Definition PathInfo.cc:32
zypp::filesystem::assert_dir
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:324
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
zypp::ManagedFile
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
zypp::asString
std::string asString(const Patch::Category &obj)
Definition Patch.cc:122
zyppng::RepoInfoWorkflow::provideKey
zypp::Pathname provideKey(SyncContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::Pathname targetDirectory_r)
Definition repoinfowf.cc:212
zyppng
Definition MediaCurl2.h:22
zyppng::makeReadyResult
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
Definition asyncop.h:297
zyppng::AsyncOpRef
std::shared_ptr< AsyncOp< T > > AsyncOpRef
Definition asyncop.h:255
zyppng::remove_smart_ptr_t
typename remove_smart_ptr< T >::type remove_smart_ptr_t
Definition type_traits.h:133
zyppng::and_then
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition expected.h:423
zyppng::transform
Container< Ret > transform(Container< Msg, CArgs... > &&val, Transformation &&transformation)
Definition transform.h:31
repoinfowf.h
reporthelper.h
zyppng::LogicBase
Definition logichelpers.h:161
zyppng::SimpleExecutor
Definition logichelpers.h:212
ManagedFile.h
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:440
ZYPP_FWD_CURRENT_EXCPT
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Definition Exception.h:436
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:424
Gettext.h
_
#define _(MSG)
Definition Gettext.h:39
MIL
#define MIL
Definition Logger.h:100
ERR
#define ERR
Definition Logger.h:102
String.h
TmpPath.h